diff options
99 files changed, 2732 insertions, 3201 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-mtd b/Documentation/ABI/testing/sysfs-class-mtd index 3105644b3bfc..bfd119ace6ad 100644 --- a/Documentation/ABI/testing/sysfs-class-mtd +++ b/Documentation/ABI/testing/sysfs-class-mtd | |||
@@ -128,9 +128,8 @@ KernelVersion: 3.4 | |||
128 | Contact: linux-mtd@lists.infradead.org | 128 | Contact: linux-mtd@lists.infradead.org |
129 | Description: | 129 | Description: |
130 | Maximum number of bit errors that the device is capable of | 130 | Maximum number of bit errors that the device is capable of |
131 | correcting within each region covering an ecc step. This will | 131 | correcting within each region covering an ECC step (see |
132 | always be a non-negative integer. Note that some devices will | 132 | ecc_step_size). This will always be a non-negative integer. |
133 | have multiple ecc steps within each writesize region. | ||
134 | 133 | ||
135 | In the case of devices lacking any ECC capability, it is 0. | 134 | In the case of devices lacking any ECC capability, it is 0. |
136 | 135 | ||
@@ -173,3 +172,15 @@ Description: | |||
173 | This is generally applicable only to NAND flash devices with ECC | 172 | This is generally applicable only to NAND flash devices with ECC |
174 | capability. It is ignored on devices lacking ECC capability; | 173 | capability. It is ignored on devices lacking ECC capability; |
175 | i.e., devices for which ecc_strength is zero. | 174 | i.e., devices for which ecc_strength is zero. |
175 | |||
176 | What: /sys/class/mtd/mtdX/ecc_step_size | ||
177 | Date: May 2013 | ||
178 | KernelVersion: 3.10 | ||
179 | Contact: linux-mtd@lists.infradead.org | ||
180 | Description: | ||
181 | The size of a single region covered by ECC, known as the ECC | ||
182 | step. Devices may have several equally sized ECC steps within | ||
183 | each writesize region. | ||
184 | |||
185 | It will always be a non-negative integer. In the case of | ||
186 | devices lacking any ECC capability, it is 0. | ||
diff --git a/Documentation/DocBook/mtdnand.tmpl b/Documentation/DocBook/mtdnand.tmpl index fe122d6e686f..a248f42a121e 100644 --- a/Documentation/DocBook/mtdnand.tmpl +++ b/Documentation/DocBook/mtdnand.tmpl | |||
@@ -1224,8 +1224,6 @@ in this page</entry> | |||
1224 | #define NAND_BBT_CREATE 0x00000200 | 1224 | #define NAND_BBT_CREATE 0x00000200 |
1225 | /* Search good / bad pattern through all pages of a block */ | 1225 | /* Search good / bad pattern through all pages of a block */ |
1226 | #define NAND_BBT_SCANALLPAGES 0x00000400 | 1226 | #define NAND_BBT_SCANALLPAGES 0x00000400 |
1227 | /* Scan block empty during good / bad block scan */ | ||
1228 | #define NAND_BBT_SCANEMPTY 0x00000800 | ||
1229 | /* Write bbt if neccecary */ | 1227 | /* Write bbt if neccecary */ |
1230 | #define NAND_BBT_WRITE 0x00001000 | 1228 | #define NAND_BBT_WRITE 0x00001000 |
1231 | /* Read and write back block contents when writing bbt */ | 1229 | /* Read and write back block contents when writing bbt */ |
diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt index d555421ea49f..c4728839d0c1 100644 --- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt +++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt | |||
@@ -15,6 +15,7 @@ Required properties: | |||
15 | optional gpio and may be set to 0 if not present. | 15 | optional gpio and may be set to 0 if not present. |
16 | 16 | ||
17 | Optional properties: | 17 | Optional properties: |
18 | - atmel,nand-has-dma : boolean to support dma transfer for nand read/write. | ||
18 | - nand-ecc-mode : String, operation mode of the NAND ecc mode, soft by default. | 19 | - nand-ecc-mode : String, operation mode of the NAND ecc mode, soft by default. |
19 | Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first", | 20 | Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first", |
20 | "soft_bch". | 21 | "soft_bch". |
@@ -29,6 +30,14 @@ Optional properties: | |||
29 | sector size 1024. | 30 | sector size 1024. |
30 | - nand-bus-width : 8 or 16 bus width if not present 8 | 31 | - nand-bus-width : 8 or 16 bus width if not present 8 |
31 | - nand-on-flash-bbt: boolean to enable on flash bbt option if not present false | 32 | - nand-on-flash-bbt: boolean to enable on flash bbt option if not present false |
33 | - Nand Flash Controller(NFC) is a slave driver under Atmel nand flash | ||
34 | - Required properties: | ||
35 | - compatible : "atmel,sama5d3-nfc". | ||
36 | - reg : should specify the address and size used for NFC command registers, | ||
37 | NFC registers and NFC Sram. NFC Sram address and size can be absent | ||
38 | if don't want to use it. | ||
39 | - Optional properties: | ||
40 | - atmel,write-by-sram: boolean to enable NFC write by sram. | ||
32 | 41 | ||
33 | Examples: | 42 | Examples: |
34 | nand0: nand@40000000,0 { | 43 | nand0: nand@40000000,0 { |
@@ -77,3 +86,22 @@ nand0: nand@40000000 { | |||
77 | ... | 86 | ... |
78 | }; | 87 | }; |
79 | }; | 88 | }; |
89 | |||
90 | /* for NFC supported chips */ | ||
91 | nand0: nand@40000000 { | ||
92 | compatible = "atmel,at91rm9200-nand"; | ||
93 | #address-cells = <1>; | ||
94 | #size-cells = <1>; | ||
95 | ranges; | ||
96 | ... | ||
97 | nfc@70000000 { | ||
98 | compatible = "atmel,sama5d3-nfc"; | ||
99 | #address-cells = <1>; | ||
100 | #size-cells = <1>; | ||
101 | reg = < | ||
102 | 0x70000000 0x10000000 /* NFC Command Registers */ | ||
103 | 0xffffc000 0x00000070 /* NFC HSMC regs */ | ||
104 | 0x00200000 0x00100000 /* NFC SRAM banks */ | ||
105 | >; | ||
106 | }; | ||
107 | }; | ||
diff --git a/Documentation/devicetree/bindings/mtd/fsmc-nand.txt b/Documentation/devicetree/bindings/mtd/fsmc-nand.txt index 2240ac09f6ba..ec42935f3908 100644 --- a/Documentation/devicetree/bindings/mtd/fsmc-nand.txt +++ b/Documentation/devicetree/bindings/mtd/fsmc-nand.txt | |||
@@ -1,4 +1,5 @@ | |||
1 | * FSMC NAND | 1 | ST Microelectronics Flexible Static Memory Controller (FSMC) |
2 | NAND Interface | ||
2 | 3 | ||
3 | Required properties: | 4 | Required properties: |
4 | - compatible : "st,spear600-fsmc-nand", "stericsson,fsmc-nand" | 5 | - compatible : "st,spear600-fsmc-nand", "stericsson,fsmc-nand" |
@@ -9,6 +10,26 @@ Optional properties: | |||
9 | - bank-width : Width (in bytes) of the device. If not present, the width | 10 | - bank-width : Width (in bytes) of the device. If not present, the width |
10 | defaults to 1 byte | 11 | defaults to 1 byte |
11 | - nand-skip-bbtscan: Indicates the the BBT scanning should be skipped | 12 | - nand-skip-bbtscan: Indicates the the BBT scanning should be skipped |
13 | - timings: array of 6 bytes for NAND timings. The meanings of these bytes | ||
14 | are: | ||
15 | byte 0 TCLR : CLE to RE delay in number of AHB clock cycles, only 4 bits | ||
16 | are valid. Zero means one clockcycle, 15 means 16 clock | ||
17 | cycles. | ||
18 | byte 1 TAR : ALE to RE delay, 4 bits are valid. Same format as TCLR. | ||
19 | byte 2 THIZ : number of HCLK clock cycles during which the data bus is | ||
20 | kept in Hi-Z (tristate) after the start of a write access. | ||
21 | Only valid for write transactions. Zero means zero cycles, | ||
22 | 255 means 255 cycles. | ||
23 | byte 3 THOLD : number of HCLK clock cycles to hold the address (and data | ||
24 | when writing) after the command deassertation. Zero means | ||
25 | one cycle, 255 means 256 cycles. | ||
26 | byte 4 TWAIT : number of HCLK clock cycles to assert the command to the | ||
27 | NAND flash in response to SMWAITn. Zero means 1 cycle, | ||
28 | 255 means 256 cycles. | ||
29 | byte 5 TSET : number of HCLK clock cycles to assert the address before the | ||
30 | command is asserted. Zero means one cycle, 255 means 256 | ||
31 | cycles. | ||
32 | - bank: default NAND bank to use (0-3 are valid, 0 is the default). | ||
12 | 33 | ||
13 | Example: | 34 | Example: |
14 | 35 | ||
@@ -24,6 +45,8 @@ Example: | |||
24 | 45 | ||
25 | bank-width = <1>; | 46 | bank-width = <1>; |
26 | nand-skip-bbtscan; | 47 | nand-skip-bbtscan; |
48 | timings = /bits/ 8 <0 0 0 2 3 0>; | ||
49 | bank = <1>; | ||
27 | 50 | ||
28 | partition@0 { | 51 | partition@0 { |
29 | ... | 52 | ... |
diff --git a/Documentation/devicetree/bindings/mtd/partition.txt b/Documentation/devicetree/bindings/mtd/partition.txt index 9315ac96b49b..8e5557da1955 100644 --- a/Documentation/devicetree/bindings/mtd/partition.txt +++ b/Documentation/devicetree/bindings/mtd/partition.txt | |||
@@ -4,6 +4,7 @@ Partitions can be represented by sub-nodes of an mtd device. This can be used | |||
4 | on platforms which have strong conventions about which portions of a flash are | 4 | on platforms which have strong conventions about which portions of a flash are |
5 | used for what purposes, but which don't use an on-flash partition table such | 5 | used for what purposes, but which don't use an on-flash partition table such |
6 | as RedBoot. | 6 | as RedBoot. |
7 | NOTE: if the sub-node has a compatible string, then it is not a partition. | ||
7 | 8 | ||
8 | #address-cells & #size-cells must both be present in the mtd device. There are | 9 | #address-cells & #size-cells must both be present in the mtd device. There are |
9 | two valid values for both: | 10 | two valid values for both: |
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index 7f8759a8a92a..a68f3cf7c3c1 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c | |||
@@ -1983,6 +1983,9 @@ at32_add_device_nand(unsigned int id, struct atmel_nand_data *data) | |||
1983 | ARRAY_SIZE(smc_cs3_resource))) | 1983 | ARRAY_SIZE(smc_cs3_resource))) |
1984 | goto fail; | 1984 | goto fail; |
1985 | 1985 | ||
1986 | /* For at32ap7000, we use the reset workaround for nand driver */ | ||
1987 | data->need_reset_workaround = true; | ||
1988 | |||
1986 | if (platform_device_add_data(pdev, data, | 1989 | if (platform_device_add_data(pdev, data, |
1987 | sizeof(struct atmel_nand_data))) | 1990 | sizeof(struct atmel_nand_data))) |
1988 | goto fail; | 1991 | goto fail; |
diff --git a/arch/mips/bcm63xx/nvram.c b/arch/mips/bcm63xx/nvram.c index e652e578a679..4b50d40f7451 100644 --- a/arch/mips/bcm63xx/nvram.c +++ b/arch/mips/bcm63xx/nvram.c | |||
@@ -35,6 +35,8 @@ struct bcm963xx_nvram { | |||
35 | u32 checksum_high; | 35 | u32 checksum_high; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | #define BCM63XX_DEFAULT_PSI_SIZE 64 | ||
39 | |||
38 | static struct bcm963xx_nvram nvram; | 40 | static struct bcm963xx_nvram nvram; |
39 | static int mac_addr_used; | 41 | static int mac_addr_used; |
40 | 42 | ||
@@ -114,3 +116,12 @@ int bcm63xx_nvram_get_mac_address(u8 *mac) | |||
114 | return 0; | 116 | return 0; |
115 | } | 117 | } |
116 | EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address); | 118 | EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address); |
119 | |||
120 | int bcm63xx_nvram_get_psi_size(void) | ||
121 | { | ||
122 | if (nvram.psi_size > 0) | ||
123 | return nvram.psi_size; | ||
124 | |||
125 | return BCM63XX_DEFAULT_PSI_SIZE; | ||
126 | } | ||
127 | EXPORT_SYMBOL(bcm63xx_nvram_get_psi_size); | ||
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h index 4e0b6bc1165e..348df49dcc9f 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h | |||
@@ -30,4 +30,6 @@ u8 *bcm63xx_nvram_get_name(void); | |||
30 | */ | 30 | */ |
31 | int bcm63xx_nvram_get_mac_address(u8 *mac); | 31 | int bcm63xx_nvram_get_mac_address(u8 *mac); |
32 | 32 | ||
33 | int bcm63xx_nvram_get_psi_size(void); | ||
34 | |||
33 | #endif /* BCM63XX_NVRAM_H */ | 35 | #endif /* BCM63XX_NVRAM_H */ |
diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c index 6eeb84c81bc2..5c813907661c 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-2012 Jonas Gorski <jonas.gorski@gmail.com> | 7 | * Copyright © 2011-2013 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 |
@@ -27,17 +27,19 @@ | |||
27 | #include <linux/crc32.h> | 27 | #include <linux/crc32.h> |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/sizes.h> | ||
30 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
31 | #include <linux/vmalloc.h> | 32 | #include <linux/vmalloc.h> |
32 | #include <linux/mtd/mtd.h> | 33 | #include <linux/mtd/mtd.h> |
33 | #include <linux/mtd/partitions.h> | 34 | #include <linux/mtd/partitions.h> |
34 | 35 | ||
36 | #include <asm/mach-bcm63xx/bcm63xx_nvram.h> | ||
35 | #include <asm/mach-bcm63xx/bcm963xx_tag.h> | 37 | #include <asm/mach-bcm63xx/bcm963xx_tag.h> |
36 | #include <asm/mach-bcm63xx/board_bcm963xx.h> | 38 | #include <asm/mach-bcm63xx/board_bcm963xx.h> |
37 | 39 | ||
38 | #define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */ | 40 | #define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */ |
39 | 41 | ||
40 | #define BCM63XX_CFE_BLOCK_SIZE 0x10000 /* always at least 64KiB */ | 42 | #define BCM63XX_CFE_BLOCK_SIZE SZ_64K /* always at least 64KiB */ |
41 | 43 | ||
42 | #define BCM63XX_CFE_MAGIC_OFFSET 0x4e0 | 44 | #define BCM63XX_CFE_MAGIC_OFFSET 0x4e0 |
43 | 45 | ||
@@ -90,7 +92,8 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master, | |||
90 | BCM63XX_CFE_BLOCK_SIZE); | 92 | BCM63XX_CFE_BLOCK_SIZE); |
91 | 93 | ||
92 | cfelen = cfe_erasesize; | 94 | cfelen = cfe_erasesize; |
93 | nvramlen = cfe_erasesize; | 95 | nvramlen = bcm63xx_nvram_get_psi_size() * SZ_1K; |
96 | nvramlen = roundup(nvramlen, cfe_erasesize); | ||
94 | 97 | ||
95 | /* Allocate memory for buffer */ | 98 | /* Allocate memory for buffer */ |
96 | buf = vmalloc(sizeof(struct bcm_tag)); | 99 | buf = vmalloc(sizeof(struct bcm_tag)); |
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index fff665d59a0d..89b9d6891532 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
@@ -1571,8 +1571,8 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1571 | xip_enable(map, chip, adr); | 1571 | xip_enable(map, chip, adr); |
1572 | /* FIXME - should have reset delay before continuing */ | 1572 | /* FIXME - should have reset delay before continuing */ |
1573 | 1573 | ||
1574 | printk(KERN_WARNING "MTD %s(): software timeout\n", | 1574 | printk(KERN_WARNING "MTD %s(): software timeout, address:0x%.8lx.\n", |
1575 | __func__ ); | 1575 | __func__, adr); |
1576 | 1576 | ||
1577 | ret = -EIO; | 1577 | ret = -EIO; |
1578 | op_done: | 1578 | op_done: |
diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c index 74dbb6bcf488..ffb36ba8a6e0 100644 --- a/drivers/mtd/chips/gen_probe.c +++ b/drivers/mtd/chips/gen_probe.c | |||
@@ -211,9 +211,7 @@ static inline struct mtd_info *cfi_cmdset_unknown(struct map_info *map, | |||
211 | 211 | ||
212 | probe_function = __symbol_get(probename); | 212 | probe_function = __symbol_get(probename); |
213 | if (!probe_function) { | 213 | if (!probe_function) { |
214 | char modname[sizeof("cfi_cmdset_%4.4X")]; | 214 | request_module("cfi_cmdset_%4.4X", type); |
215 | sprintf(modname, "cfi_cmdset_%4.4X", type); | ||
216 | request_module(modname); | ||
217 | probe_function = __symbol_get(probename); | 215 | probe_function = __symbol_get(probename); |
218 | } | 216 | } |
219 | 217 | ||
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index c443f527a53a..7c0b27d132b1 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c | |||
@@ -120,7 +120,7 @@ | |||
120 | #define PM49FL008 0x006A | 120 | #define PM49FL008 0x006A |
121 | 121 | ||
122 | /* Sharp */ | 122 | /* Sharp */ |
123 | #define LH28F640BF 0x00b0 | 123 | #define LH28F640BF 0x00B0 |
124 | 124 | ||
125 | /* ST - www.st.com */ | 125 | /* ST - www.st.com */ |
126 | #define M29F800AB 0x0058 | 126 | #define M29F800AB 0x0058 |
@@ -1299,13 +1299,14 @@ static const struct amd_flash_info jedec_table[] = { | |||
1299 | .mfr_id = CFI_MFR_SHARP, | 1299 | .mfr_id = CFI_MFR_SHARP, |
1300 | .dev_id = LH28F640BF, | 1300 | .dev_id = LH28F640BF, |
1301 | .name = "LH28F640BF", | 1301 | .name = "LH28F640BF", |
1302 | .devtypes = CFI_DEVICETYPE_X8, | 1302 | .devtypes = CFI_DEVICETYPE_X16, |
1303 | .uaddr = MTD_UADDR_UNNECESSARY, | 1303 | .uaddr = MTD_UADDR_UNNECESSARY, |
1304 | .dev_size = SIZE_4MiB, | 1304 | .dev_size = SIZE_8MiB, |
1305 | .cmd_set = P_ID_INTEL_STD, | 1305 | .cmd_set = P_ID_INTEL_EXT, |
1306 | .nr_regions = 1, | 1306 | .nr_regions = 2, |
1307 | .regions = { | 1307 | .regions = { |
1308 | ERASEINFO(0x40000,16), | 1308 | ERASEINFO(0x10000, 127), |
1309 | ERASEINFO(0x02000, 8), | ||
1309 | } | 1310 | } |
1310 | }, { | 1311 | }, { |
1311 | .mfr_id = CFI_MFR_SST, | 1312 | .mfr_id = CFI_MFR_SST, |
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 2a4d55e4b362..74ab4b7e523e 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig | |||
@@ -224,59 +224,4 @@ config BCH_CONST_T | |||
224 | default 4 | 224 | default 4 |
225 | endif | 225 | endif |
226 | 226 | ||
227 | config MTD_DOCPROBE | ||
228 | tristate | ||
229 | select MTD_DOCECC | ||
230 | |||
231 | config MTD_DOCECC | ||
232 | tristate | ||
233 | |||
234 | config MTD_DOCPROBE_ADVANCED | ||
235 | bool "Advanced detection options for DiskOnChip" | ||
236 | depends on MTD_DOCPROBE | ||
237 | help | ||
238 | This option allows you to specify nonstandard address at which to | ||
239 | probe for a DiskOnChip, or to change the detection options. You | ||
240 | are unlikely to need any of this unless you are using LinuxBIOS. | ||
241 | Say 'N'. | ||
242 | |||
243 | config MTD_DOCPROBE_ADDRESS | ||
244 | hex "Physical address of DiskOnChip" if MTD_DOCPROBE_ADVANCED | ||
245 | depends on MTD_DOCPROBE | ||
246 | default "0x0" | ||
247 | ---help--- | ||
248 | By default, the probe for DiskOnChip devices will look for a | ||
249 | DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000. | ||
250 | This option allows you to specify a single address at which to probe | ||
251 | for the device, which is useful if you have other devices in that | ||
252 | range which get upset when they are probed. | ||
253 | |||
254 | (Note that on PowerPC, the normal probe will only check at | ||
255 | 0xE4000000.) | ||
256 | |||
257 | Normally, you should leave this set to zero, to allow the probe at | ||
258 | the normal addresses. | ||
259 | |||
260 | config MTD_DOCPROBE_HIGH | ||
261 | bool "Probe high addresses" | ||
262 | depends on MTD_DOCPROBE_ADVANCED | ||
263 | help | ||
264 | By default, the probe for DiskOnChip devices will look for a | ||
265 | DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000. | ||
266 | This option changes to make it probe between 0xFFFC8000 and | ||
267 | 0xFFFEE000. Unless you are using LinuxBIOS, this is unlikely to be | ||
268 | useful to you. Say 'N'. | ||
269 | |||
270 | config MTD_DOCPROBE_55AA | ||
271 | bool "Probe for 0x55 0xAA BIOS Extension Signature" | ||
272 | depends on MTD_DOCPROBE_ADVANCED | ||
273 | help | ||
274 | Check for the 0x55 0xAA signature of a DiskOnChip, and do not | ||
275 | continue with probing if it is absent. The signature will always be | ||
276 | present for a DiskOnChip 2000 or a normal DiskOnChip Millennium. | ||
277 | Only if you have overwritten the first block of a DiskOnChip | ||
278 | Millennium will it be absent. Enable this option if you are using | ||
279 | LinuxBIOS or if you need to recover a DiskOnChip Millennium on which | ||
280 | you have managed to wipe the first block. | ||
281 | |||
282 | endmenu | 227 | endmenu |
diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c index 18e7761137a3..77de29bc02ba 100644 --- a/drivers/mtd/devices/bcm47xxsflash.c +++ b/drivers/mtd/devices/bcm47xxsflash.c | |||
@@ -1,6 +1,7 @@ | |||
1 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
2 | #include <linux/module.h> | 2 | #include <linux/module.h> |
3 | #include <linux/slab.h> | 3 | #include <linux/slab.h> |
4 | #include <linux/delay.h> | ||
4 | #include <linux/mtd/mtd.h> | 5 | #include <linux/mtd/mtd.h> |
5 | #include <linux/platform_device.h> | 6 | #include <linux/platform_device.h> |
6 | #include <linux/bcma/bcma.h> | 7 | #include <linux/bcma/bcma.h> |
@@ -12,6 +13,93 @@ MODULE_DESCRIPTION("Serial flash driver for BCMA bus"); | |||
12 | 13 | ||
13 | static const char * const probes[] = { "bcm47xxpart", NULL }; | 14 | static const char * const probes[] = { "bcm47xxpart", NULL }; |
14 | 15 | ||
16 | /************************************************** | ||
17 | * Various helpers | ||
18 | **************************************************/ | ||
19 | |||
20 | static void bcm47xxsflash_cmd(struct bcm47xxsflash *b47s, u32 opcode) | ||
21 | { | ||
22 | int i; | ||
23 | |||
24 | b47s->cc_write(b47s, BCMA_CC_FLASHCTL, BCMA_CC_FLASHCTL_START | opcode); | ||
25 | for (i = 0; i < 1000; i++) { | ||
26 | if (!(b47s->cc_read(b47s, BCMA_CC_FLASHCTL) & | ||
27 | BCMA_CC_FLASHCTL_BUSY)) | ||
28 | return; | ||
29 | cpu_relax(); | ||
30 | } | ||
31 | pr_err("Control command failed (timeout)!\n"); | ||
32 | } | ||
33 | |||
34 | static int bcm47xxsflash_poll(struct bcm47xxsflash *b47s, int timeout) | ||
35 | { | ||
36 | unsigned long deadline = jiffies + timeout; | ||
37 | |||
38 | do { | ||
39 | switch (b47s->type) { | ||
40 | case BCM47XXSFLASH_TYPE_ST: | ||
41 | bcm47xxsflash_cmd(b47s, OPCODE_ST_RDSR); | ||
42 | if (!(b47s->cc_read(b47s, BCMA_CC_FLASHDATA) & | ||
43 | SR_ST_WIP)) | ||
44 | return 0; | ||
45 | break; | ||
46 | case BCM47XXSFLASH_TYPE_ATMEL: | ||
47 | bcm47xxsflash_cmd(b47s, OPCODE_AT_STATUS); | ||
48 | if (b47s->cc_read(b47s, BCMA_CC_FLASHDATA) & | ||
49 | SR_AT_READY) | ||
50 | return 0; | ||
51 | break; | ||
52 | } | ||
53 | |||
54 | cpu_relax(); | ||
55 | udelay(1); | ||
56 | } while (!time_after_eq(jiffies, deadline)); | ||
57 | |||
58 | pr_err("Timeout waiting for flash to be ready!\n"); | ||
59 | |||
60 | return -EBUSY; | ||
61 | } | ||
62 | |||
63 | /************************************************** | ||
64 | * MTD ops | ||
65 | **************************************************/ | ||
66 | |||
67 | static int bcm47xxsflash_erase(struct mtd_info *mtd, struct erase_info *erase) | ||
68 | { | ||
69 | struct bcm47xxsflash *b47s = mtd->priv; | ||
70 | int err; | ||
71 | |||
72 | switch (b47s->type) { | ||
73 | case BCM47XXSFLASH_TYPE_ST: | ||
74 | bcm47xxsflash_cmd(b47s, OPCODE_ST_WREN); | ||
75 | b47s->cc_write(b47s, BCMA_CC_FLASHADDR, erase->addr); | ||
76 | /* Newer flashes have "sub-sectors" which can be erased | ||
77 | * independently with a new command: ST_SSE. The ST_SE command | ||
78 | * erases 64KB just as before. | ||
79 | */ | ||
80 | if (b47s->blocksize < (64 * 1024)) | ||
81 | bcm47xxsflash_cmd(b47s, OPCODE_ST_SSE); | ||
82 | else | ||
83 | bcm47xxsflash_cmd(b47s, OPCODE_ST_SE); | ||
84 | break; | ||
85 | case BCM47XXSFLASH_TYPE_ATMEL: | ||
86 | b47s->cc_write(b47s, BCMA_CC_FLASHADDR, erase->addr << 1); | ||
87 | bcm47xxsflash_cmd(b47s, OPCODE_AT_PAGE_ERASE); | ||
88 | break; | ||
89 | } | ||
90 | |||
91 | err = bcm47xxsflash_poll(b47s, HZ); | ||
92 | if (err) | ||
93 | erase->state = MTD_ERASE_FAILED; | ||
94 | else | ||
95 | erase->state = MTD_ERASE_DONE; | ||
96 | |||
97 | if (erase->callback) | ||
98 | erase->callback(erase); | ||
99 | |||
100 | return err; | ||
101 | } | ||
102 | |||
15 | static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len, | 103 | static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len, |
16 | size_t *retlen, u_char *buf) | 104 | size_t *retlen, u_char *buf) |
17 | { | 105 | { |
@@ -28,6 +116,127 @@ static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
28 | return len; | 116 | return len; |
29 | } | 117 | } |
30 | 118 | ||
119 | static int bcm47xxsflash_write_st(struct mtd_info *mtd, u32 offset, size_t len, | ||
120 | const u_char *buf) | ||
121 | { | ||
122 | struct bcm47xxsflash *b47s = mtd->priv; | ||
123 | int written = 0; | ||
124 | |||
125 | /* Enable writes */ | ||
126 | bcm47xxsflash_cmd(b47s, OPCODE_ST_WREN); | ||
127 | |||
128 | /* Write first byte */ | ||
129 | b47s->cc_write(b47s, BCMA_CC_FLASHADDR, offset); | ||
130 | b47s->cc_write(b47s, BCMA_CC_FLASHDATA, *buf++); | ||
131 | |||
132 | /* Program page */ | ||
133 | if (b47s->bcma_cc->core->id.rev < 20) { | ||
134 | bcm47xxsflash_cmd(b47s, OPCODE_ST_PP); | ||
135 | return 1; /* 1B written */ | ||
136 | } | ||
137 | |||
138 | /* Program page and set CSA (on newer chips we can continue writing) */ | ||
139 | bcm47xxsflash_cmd(b47s, OPCODE_ST_CSA | OPCODE_ST_PP); | ||
140 | offset++; | ||
141 | len--; | ||
142 | written++; | ||
143 | |||
144 | while (len > 0) { | ||
145 | /* Page boundary, another function call is needed */ | ||
146 | if ((offset & 0xFF) == 0) | ||
147 | break; | ||
148 | |||
149 | bcm47xxsflash_cmd(b47s, OPCODE_ST_CSA | *buf++); | ||
150 | offset++; | ||
151 | len--; | ||
152 | written++; | ||
153 | } | ||
154 | |||
155 | /* All done, drop CSA & poll */ | ||
156 | b47s->cc_write(b47s, BCMA_CC_FLASHCTL, 0); | ||
157 | udelay(1); | ||
158 | if (bcm47xxsflash_poll(b47s, HZ / 10)) | ||
159 | pr_err("Flash rejected dropping CSA\n"); | ||
160 | |||
161 | return written; | ||
162 | } | ||
163 | |||
164 | static int bcm47xxsflash_write_at(struct mtd_info *mtd, u32 offset, size_t len, | ||
165 | const u_char *buf) | ||
166 | { | ||
167 | struct bcm47xxsflash *b47s = mtd->priv; | ||
168 | u32 mask = b47s->blocksize - 1; | ||
169 | u32 page = (offset & ~mask) << 1; | ||
170 | u32 byte = offset & mask; | ||
171 | int written = 0; | ||
172 | |||
173 | /* If we don't overwrite whole page, read it to the buffer first */ | ||
174 | if (byte || (len < b47s->blocksize)) { | ||
175 | int err; | ||
176 | |||
177 | b47s->cc_write(b47s, BCMA_CC_FLASHADDR, page); | ||
178 | bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_LOAD); | ||
179 | /* 250 us for AT45DB321B */ | ||
180 | err = bcm47xxsflash_poll(b47s, HZ / 1000); | ||
181 | if (err) { | ||
182 | pr_err("Timeout reading page 0x%X info buffer\n", page); | ||
183 | return err; | ||
184 | } | ||
185 | } | ||
186 | |||
187 | /* Change buffer content with our data */ | ||
188 | while (len > 0) { | ||
189 | /* Page boundary, another function call is needed */ | ||
190 | if (byte == b47s->blocksize) | ||
191 | break; | ||
192 | |||
193 | b47s->cc_write(b47s, BCMA_CC_FLASHADDR, byte++); | ||
194 | b47s->cc_write(b47s, BCMA_CC_FLASHDATA, *buf++); | ||
195 | bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_WRITE); | ||
196 | len--; | ||
197 | written++; | ||
198 | } | ||
199 | |||
200 | /* Program page with the buffer content */ | ||
201 | b47s->cc_write(b47s, BCMA_CC_FLASHADDR, page); | ||
202 | bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_PROGRAM); | ||
203 | |||
204 | return written; | ||
205 | } | ||
206 | |||
207 | static int bcm47xxsflash_write(struct mtd_info *mtd, loff_t to, size_t len, | ||
208 | size_t *retlen, const u_char *buf) | ||
209 | { | ||
210 | struct bcm47xxsflash *b47s = mtd->priv; | ||
211 | int written; | ||
212 | |||
213 | /* Writing functions can return without writing all passed data, for | ||
214 | * example when the hardware is too old or when we git page boundary. | ||
215 | */ | ||
216 | while (len > 0) { | ||
217 | switch (b47s->type) { | ||
218 | case BCM47XXSFLASH_TYPE_ST: | ||
219 | written = bcm47xxsflash_write_st(mtd, to, len, buf); | ||
220 | break; | ||
221 | case BCM47XXSFLASH_TYPE_ATMEL: | ||
222 | written = bcm47xxsflash_write_at(mtd, to, len, buf); | ||
223 | break; | ||
224 | default: | ||
225 | BUG_ON(1); | ||
226 | } | ||
227 | if (written < 0) { | ||
228 | pr_err("Error writing at offset 0x%llX\n", to); | ||
229 | return written; | ||
230 | } | ||
231 | to += (loff_t)written; | ||
232 | len -= written; | ||
233 | *retlen += written; | ||
234 | buf += written; | ||
235 | } | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
31 | static void bcm47xxsflash_fill_mtd(struct bcm47xxsflash *b47s) | 240 | static void bcm47xxsflash_fill_mtd(struct bcm47xxsflash *b47s) |
32 | { | 241 | { |
33 | struct mtd_info *mtd = &b47s->mtd; | 242 | struct mtd_info *mtd = &b47s->mtd; |
@@ -35,33 +244,48 @@ static void bcm47xxsflash_fill_mtd(struct bcm47xxsflash *b47s) | |||
35 | mtd->priv = b47s; | 244 | mtd->priv = b47s; |
36 | mtd->name = "bcm47xxsflash"; | 245 | mtd->name = "bcm47xxsflash"; |
37 | mtd->owner = THIS_MODULE; | 246 | mtd->owner = THIS_MODULE; |
38 | mtd->type = MTD_ROM; | 247 | |
248 | mtd->type = MTD_NORFLASH; | ||
249 | mtd->flags = MTD_CAP_NORFLASH; | ||
39 | mtd->size = b47s->size; | 250 | mtd->size = b47s->size; |
40 | mtd->_read = bcm47xxsflash_read; | 251 | mtd->erasesize = b47s->blocksize; |
252 | mtd->writesize = 1; | ||
253 | mtd->writebufsize = 1; | ||
41 | 254 | ||
42 | /* TODO: implement writing support and verify/change following code */ | 255 | mtd->_erase = bcm47xxsflash_erase; |
43 | mtd->flags = MTD_CAP_ROM; | 256 | mtd->_read = bcm47xxsflash_read; |
44 | mtd->writebufsize = mtd->writesize = 1; | 257 | mtd->_write = bcm47xxsflash_write; |
45 | } | 258 | } |
46 | 259 | ||
47 | /************************************************** | 260 | /************************************************** |
48 | * BCMA | 261 | * BCMA |
49 | **************************************************/ | 262 | **************************************************/ |
50 | 263 | ||
264 | static int bcm47xxsflash_bcma_cc_read(struct bcm47xxsflash *b47s, u16 offset) | ||
265 | { | ||
266 | return bcma_cc_read32(b47s->bcma_cc, offset); | ||
267 | } | ||
268 | |||
269 | static void bcm47xxsflash_bcma_cc_write(struct bcm47xxsflash *b47s, u16 offset, | ||
270 | u32 value) | ||
271 | { | ||
272 | bcma_cc_write32(b47s->bcma_cc, offset, value); | ||
273 | } | ||
274 | |||
51 | static int bcm47xxsflash_bcma_probe(struct platform_device *pdev) | 275 | static int bcm47xxsflash_bcma_probe(struct platform_device *pdev) |
52 | { | 276 | { |
53 | struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev); | 277 | struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev); |
54 | struct bcm47xxsflash *b47s; | 278 | struct bcm47xxsflash *b47s; |
55 | int err; | 279 | int err; |
56 | 280 | ||
57 | b47s = kzalloc(sizeof(*b47s), GFP_KERNEL); | 281 | b47s = devm_kzalloc(&pdev->dev, sizeof(*b47s), GFP_KERNEL); |
58 | if (!b47s) { | 282 | if (!b47s) |
59 | err = -ENOMEM; | 283 | return -ENOMEM; |
60 | goto out; | ||
61 | } | ||
62 | sflash->priv = b47s; | 284 | sflash->priv = b47s; |
63 | 285 | ||
64 | b47s->bcma_cc = container_of(sflash, struct bcma_drv_cc, sflash); | 286 | b47s->bcma_cc = container_of(sflash, struct bcma_drv_cc, sflash); |
287 | b47s->cc_read = bcm47xxsflash_bcma_cc_read; | ||
288 | b47s->cc_write = bcm47xxsflash_bcma_cc_write; | ||
65 | 289 | ||
66 | switch (b47s->bcma_cc->capabilities & BCMA_CC_CAP_FLASHT) { | 290 | switch (b47s->bcma_cc->capabilities & BCMA_CC_CAP_FLASHT) { |
67 | case BCMA_CC_FLASHT_STSER: | 291 | case BCMA_CC_FLASHT_STSER: |
@@ -81,15 +305,13 @@ static int bcm47xxsflash_bcma_probe(struct platform_device *pdev) | |||
81 | err = mtd_device_parse_register(&b47s->mtd, probes, NULL, NULL, 0); | 305 | err = mtd_device_parse_register(&b47s->mtd, probes, NULL, NULL, 0); |
82 | if (err) { | 306 | if (err) { |
83 | pr_err("Failed to register MTD device: %d\n", err); | 307 | pr_err("Failed to register MTD device: %d\n", err); |
84 | goto err_dev_reg; | 308 | return err; |
85 | } | 309 | } |
86 | 310 | ||
87 | return 0; | 311 | if (bcm47xxsflash_poll(b47s, HZ / 10)) |
312 | pr_warn("Serial flash busy\n"); | ||
88 | 313 | ||
89 | err_dev_reg: | 314 | return 0; |
90 | kfree(&b47s->mtd); | ||
91 | out: | ||
92 | return err; | ||
93 | } | 315 | } |
94 | 316 | ||
95 | static int bcm47xxsflash_bcma_remove(struct platform_device *pdev) | 317 | static int bcm47xxsflash_bcma_remove(struct platform_device *pdev) |
@@ -98,7 +320,6 @@ static int bcm47xxsflash_bcma_remove(struct platform_device *pdev) | |||
98 | struct bcm47xxsflash *b47s = sflash->priv; | 320 | struct bcm47xxsflash *b47s = sflash->priv; |
99 | 321 | ||
100 | mtd_device_unregister(&b47s->mtd); | 322 | mtd_device_unregister(&b47s->mtd); |
101 | kfree(b47s); | ||
102 | 323 | ||
103 | return 0; | 324 | return 0; |
104 | } | 325 | } |
@@ -116,22 +337,4 @@ static struct platform_driver bcma_sflash_driver = { | |||
116 | * Init | 337 | * Init |
117 | **************************************************/ | 338 | **************************************************/ |
118 | 339 | ||
119 | static int __init bcm47xxsflash_init(void) | 340 | module_platform_driver(bcma_sflash_driver); |
120 | { | ||
121 | int err; | ||
122 | |||
123 | err = platform_driver_register(&bcma_sflash_driver); | ||
124 | if (err) | ||
125 | pr_err("Failed to register BCMA serial flash driver: %d\n", | ||
126 | err); | ||
127 | |||
128 | return err; | ||
129 | } | ||
130 | |||
131 | static void __exit bcm47xxsflash_exit(void) | ||
132 | { | ||
133 | platform_driver_unregister(&bcma_sflash_driver); | ||
134 | } | ||
135 | |||
136 | module_init(bcm47xxsflash_init); | ||
137 | module_exit(bcm47xxsflash_exit); | ||
diff --git a/drivers/mtd/devices/bcm47xxsflash.h b/drivers/mtd/devices/bcm47xxsflash.h index f22f8c46dfc0..fe93daf4f489 100644 --- a/drivers/mtd/devices/bcm47xxsflash.h +++ b/drivers/mtd/devices/bcm47xxsflash.h | |||
@@ -60,6 +60,8 @@ enum bcm47xxsflash_type { | |||
60 | 60 | ||
61 | struct bcm47xxsflash { | 61 | struct bcm47xxsflash { |
62 | struct bcma_drv_cc *bcma_cc; | 62 | struct bcma_drv_cc *bcma_cc; |
63 | int (*cc_read)(struct bcm47xxsflash *b47s, u16 offset); | ||
64 | void (*cc_write)(struct bcm47xxsflash *b47s, u16 offset, u32 value); | ||
63 | 65 | ||
64 | enum bcm47xxsflash_type type; | 66 | enum bcm47xxsflash_type type; |
65 | 67 | ||
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index e081bfeaaf7d..5cb4c04726b2 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c | |||
@@ -6,6 +6,9 @@ | |||
6 | * | 6 | * |
7 | * Licence: GPL | 7 | * Licence: GPL |
8 | */ | 8 | */ |
9 | |||
10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
11 | |||
9 | #include <linux/module.h> | 12 | #include <linux/module.h> |
10 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
11 | #include <linux/blkdev.h> | 14 | #include <linux/blkdev.h> |
@@ -18,10 +21,6 @@ | |||
18 | #include <linux/mount.h> | 21 | #include <linux/mount.h> |
19 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
20 | 23 | ||
21 | #define ERROR(fmt, args...) printk(KERN_ERR "block2mtd: " fmt "\n" , ## args) | ||
22 | #define INFO(fmt, args...) printk(KERN_INFO "block2mtd: " fmt "\n" , ## args) | ||
23 | |||
24 | |||
25 | /* Info for the block device */ | 24 | /* Info for the block device */ |
26 | struct block2mtd_dev { | 25 | struct block2mtd_dev { |
27 | struct list_head list; | 26 | struct list_head list; |
@@ -84,7 +83,7 @@ static int block2mtd_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
84 | err = _block2mtd_erase(dev, from, len); | 83 | err = _block2mtd_erase(dev, from, len); |
85 | mutex_unlock(&dev->write_mutex); | 84 | mutex_unlock(&dev->write_mutex); |
86 | if (err) { | 85 | if (err) { |
87 | ERROR("erase failed err = %d", err); | 86 | pr_err("erase failed err = %d\n", err); |
88 | instr->state = MTD_ERASE_FAILED; | 87 | instr->state = MTD_ERASE_FAILED; |
89 | } else | 88 | } else |
90 | instr->state = MTD_ERASE_DONE; | 89 | instr->state = MTD_ERASE_DONE; |
@@ -239,13 +238,13 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) | |||
239 | #endif | 238 | #endif |
240 | 239 | ||
241 | if (IS_ERR(bdev)) { | 240 | if (IS_ERR(bdev)) { |
242 | ERROR("error: cannot open device %s", devname); | 241 | pr_err("error: cannot open device %s\n", devname); |
243 | goto devinit_err; | 242 | goto devinit_err; |
244 | } | 243 | } |
245 | dev->blkdev = bdev; | 244 | dev->blkdev = bdev; |
246 | 245 | ||
247 | if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) { | 246 | if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) { |
248 | ERROR("attempting to use an MTD device as a block device"); | 247 | pr_err("attempting to use an MTD device as a block device\n"); |
249 | goto devinit_err; | 248 | goto devinit_err; |
250 | } | 249 | } |
251 | 250 | ||
@@ -277,9 +276,10 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) | |||
277 | goto devinit_err; | 276 | goto devinit_err; |
278 | } | 277 | } |
279 | list_add(&dev->list, &blkmtd_device_list); | 278 | list_add(&dev->list, &blkmtd_device_list); |
280 | INFO("mtd%d: [%s] erase_size = %dKiB [%d]", dev->mtd.index, | 279 | pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n", |
281 | dev->mtd.name + strlen("block2mtd: "), | 280 | dev->mtd.index, |
282 | dev->mtd.erasesize >> 10, dev->mtd.erasesize); | 281 | dev->mtd.name + strlen("block2mtd: "), |
282 | dev->mtd.erasesize >> 10, dev->mtd.erasesize); | ||
283 | return dev; | 283 | return dev; |
284 | 284 | ||
285 | devinit_err: | 285 | devinit_err: |
@@ -339,17 +339,11 @@ static inline void kill_final_newline(char *str) | |||
339 | } | 339 | } |
340 | 340 | ||
341 | 341 | ||
342 | #define parse_err(fmt, args...) do { \ | ||
343 | ERROR(fmt, ## args); \ | ||
344 | return 0; \ | ||
345 | } while (0) | ||
346 | |||
347 | #ifndef MODULE | 342 | #ifndef MODULE |
348 | static int block2mtd_init_called = 0; | 343 | static int block2mtd_init_called = 0; |
349 | static char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */ | 344 | static char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */ |
350 | #endif | 345 | #endif |
351 | 346 | ||
352 | |||
353 | static int block2mtd_setup2(const char *val) | 347 | static int block2mtd_setup2(const char *val) |
354 | { | 348 | { |
355 | char buf[80 + 12]; /* 80 for device, 12 for erase size */ | 349 | char buf[80 + 12]; /* 80 for device, 12 for erase size */ |
@@ -359,8 +353,10 @@ static int block2mtd_setup2(const char *val) | |||
359 | size_t erase_size = PAGE_SIZE; | 353 | size_t erase_size = PAGE_SIZE; |
360 | int i, ret; | 354 | int i, ret; |
361 | 355 | ||
362 | if (strnlen(val, sizeof(buf)) >= sizeof(buf)) | 356 | if (strnlen(val, sizeof(buf)) >= sizeof(buf)) { |
363 | parse_err("parameter too long"); | 357 | pr_err("parameter too long\n"); |
358 | return 0; | ||
359 | } | ||
364 | 360 | ||
365 | strcpy(str, val); | 361 | strcpy(str, val); |
366 | kill_final_newline(str); | 362 | kill_final_newline(str); |
@@ -368,20 +364,27 @@ static int block2mtd_setup2(const char *val) | |||
368 | for (i = 0; i < 2; i++) | 364 | for (i = 0; i < 2; i++) |
369 | token[i] = strsep(&str, ","); | 365 | token[i] = strsep(&str, ","); |
370 | 366 | ||
371 | if (str) | 367 | if (str) { |
372 | parse_err("too many arguments"); | 368 | pr_err("too many arguments\n"); |
369 | return 0; | ||
370 | } | ||
373 | 371 | ||
374 | if (!token[0]) | 372 | if (!token[0]) { |
375 | parse_err("no argument"); | 373 | pr_err("no argument\n"); |
374 | return 0; | ||
375 | } | ||
376 | 376 | ||
377 | name = token[0]; | 377 | name = token[0]; |
378 | if (strlen(name) + 1 > 80) | 378 | if (strlen(name) + 1 > 80) { |
379 | parse_err("device name too long"); | 379 | pr_err("device name too long\n"); |
380 | return 0; | ||
381 | } | ||
380 | 382 | ||
381 | if (token[1]) { | 383 | if (token[1]) { |
382 | ret = parse_num(&erase_size, token[1]); | 384 | ret = parse_num(&erase_size, token[1]); |
383 | if (ret) { | 385 | if (ret) { |
384 | parse_err("illegal erase size"); | 386 | pr_err("illegal erase size\n"); |
387 | return 0; | ||
385 | } | 388 | } |
386 | } | 389 | } |
387 | 390 | ||
@@ -444,8 +447,9 @@ static void block2mtd_exit(void) | |||
444 | struct block2mtd_dev *dev = list_entry(pos, typeof(*dev), list); | 447 | struct block2mtd_dev *dev = list_entry(pos, typeof(*dev), list); |
445 | block2mtd_sync(&dev->mtd); | 448 | block2mtd_sync(&dev->mtd); |
446 | mtd_device_unregister(&dev->mtd); | 449 | mtd_device_unregister(&dev->mtd); |
447 | INFO("mtd%d: [%s] removed", dev->mtd.index, | 450 | pr_info("mtd%d: [%s] removed\n", |
448 | dev->mtd.name + strlen("block2mtd: ")); | 451 | dev->mtd.index, |
452 | dev->mtd.name + strlen("block2mtd: ")); | ||
449 | list_del(&dev->list); | 453 | list_del(&dev->list); |
450 | block2mtd_free_device(dev); | 454 | block2mtd_free_device(dev); |
451 | } | 455 | } |
diff --git a/drivers/mtd/devices/elm.c b/drivers/mtd/devices/elm.c index dccef9fdc1f2..d1dd6a33a050 100644 --- a/drivers/mtd/devices/elm.c +++ b/drivers/mtd/devices/elm.c | |||
@@ -20,14 +20,21 @@ | |||
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <linux/of.h> | 22 | #include <linux/of.h> |
23 | #include <linux/sched.h> | ||
23 | #include <linux/pm_runtime.h> | 24 | #include <linux/pm_runtime.h> |
24 | #include <linux/platform_data/elm.h> | 25 | #include <linux/platform_data/elm.h> |
25 | 26 | ||
27 | #define ELM_SYSCONFIG 0x010 | ||
26 | #define ELM_IRQSTATUS 0x018 | 28 | #define ELM_IRQSTATUS 0x018 |
27 | #define ELM_IRQENABLE 0x01c | 29 | #define ELM_IRQENABLE 0x01c |
28 | #define ELM_LOCATION_CONFIG 0x020 | 30 | #define ELM_LOCATION_CONFIG 0x020 |
29 | #define ELM_PAGE_CTRL 0x080 | 31 | #define ELM_PAGE_CTRL 0x080 |
30 | #define ELM_SYNDROME_FRAGMENT_0 0x400 | 32 | #define ELM_SYNDROME_FRAGMENT_0 0x400 |
33 | #define ELM_SYNDROME_FRAGMENT_1 0x404 | ||
34 | #define ELM_SYNDROME_FRAGMENT_2 0x408 | ||
35 | #define ELM_SYNDROME_FRAGMENT_3 0x40c | ||
36 | #define ELM_SYNDROME_FRAGMENT_4 0x410 | ||
37 | #define ELM_SYNDROME_FRAGMENT_5 0x414 | ||
31 | #define ELM_SYNDROME_FRAGMENT_6 0x418 | 38 | #define ELM_SYNDROME_FRAGMENT_6 0x418 |
32 | #define ELM_LOCATION_STATUS 0x800 | 39 | #define ELM_LOCATION_STATUS 0x800 |
33 | #define ELM_ERROR_LOCATION_0 0x880 | 40 | #define ELM_ERROR_LOCATION_0 0x880 |
@@ -56,12 +63,27 @@ | |||
56 | #define SYNDROME_FRAGMENT_REG_SIZE 0x40 | 63 | #define SYNDROME_FRAGMENT_REG_SIZE 0x40 |
57 | #define ERROR_LOCATION_SIZE 0x100 | 64 | #define ERROR_LOCATION_SIZE 0x100 |
58 | 65 | ||
66 | struct elm_registers { | ||
67 | u32 elm_irqenable; | ||
68 | u32 elm_sysconfig; | ||
69 | u32 elm_location_config; | ||
70 | u32 elm_page_ctrl; | ||
71 | u32 elm_syndrome_fragment_6[ERROR_VECTOR_MAX]; | ||
72 | u32 elm_syndrome_fragment_5[ERROR_VECTOR_MAX]; | ||
73 | u32 elm_syndrome_fragment_4[ERROR_VECTOR_MAX]; | ||
74 | u32 elm_syndrome_fragment_3[ERROR_VECTOR_MAX]; | ||
75 | u32 elm_syndrome_fragment_2[ERROR_VECTOR_MAX]; | ||
76 | u32 elm_syndrome_fragment_1[ERROR_VECTOR_MAX]; | ||
77 | u32 elm_syndrome_fragment_0[ERROR_VECTOR_MAX]; | ||
78 | }; | ||
79 | |||
59 | struct elm_info { | 80 | struct elm_info { |
60 | struct device *dev; | 81 | struct device *dev; |
61 | void __iomem *elm_base; | 82 | void __iomem *elm_base; |
62 | struct completion elm_completion; | 83 | struct completion elm_completion; |
63 | struct list_head list; | 84 | struct list_head list; |
64 | enum bch_ecc bch_type; | 85 | enum bch_ecc bch_type; |
86 | struct elm_registers elm_regs; | ||
65 | }; | 87 | }; |
66 | 88 | ||
67 | static LIST_HEAD(elm_devices); | 89 | static LIST_HEAD(elm_devices); |
@@ -346,14 +368,9 @@ static int elm_probe(struct platform_device *pdev) | |||
346 | } | 368 | } |
347 | 369 | ||
348 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 370 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
349 | if (!res) { | 371 | info->elm_base = devm_ioremap_resource(&pdev->dev, res); |
350 | dev_err(&pdev->dev, "no memory resource defined\n"); | 372 | if (IS_ERR(info->elm_base)) |
351 | return -ENODEV; | 373 | return PTR_ERR(info->elm_base); |
352 | } | ||
353 | |||
354 | info->elm_base = devm_request_and_ioremap(&pdev->dev, res); | ||
355 | if (!info->elm_base) | ||
356 | return -EADDRNOTAVAIL; | ||
357 | 374 | ||
358 | ret = devm_request_irq(&pdev->dev, irq->start, elm_isr, 0, | 375 | ret = devm_request_irq(&pdev->dev, irq->start, elm_isr, 0, |
359 | pdev->name, info); | 376 | pdev->name, info); |
@@ -381,10 +398,103 @@ static int elm_remove(struct platform_device *pdev) | |||
381 | { | 398 | { |
382 | pm_runtime_put_sync(&pdev->dev); | 399 | pm_runtime_put_sync(&pdev->dev); |
383 | pm_runtime_disable(&pdev->dev); | 400 | pm_runtime_disable(&pdev->dev); |
384 | platform_set_drvdata(pdev, NULL); | ||
385 | return 0; | 401 | return 0; |
386 | } | 402 | } |
387 | 403 | ||
404 | /** | ||
405 | * elm_context_save | ||
406 | * saves ELM configurations to preserve them across Hardware powered-down | ||
407 | */ | ||
408 | static int elm_context_save(struct elm_info *info) | ||
409 | { | ||
410 | struct elm_registers *regs = &info->elm_regs; | ||
411 | enum bch_ecc bch_type = info->bch_type; | ||
412 | u32 offset = 0, i; | ||
413 | |||
414 | regs->elm_irqenable = elm_read_reg(info, ELM_IRQENABLE); | ||
415 | regs->elm_sysconfig = elm_read_reg(info, ELM_SYSCONFIG); | ||
416 | regs->elm_location_config = elm_read_reg(info, ELM_LOCATION_CONFIG); | ||
417 | regs->elm_page_ctrl = elm_read_reg(info, ELM_PAGE_CTRL); | ||
418 | for (i = 0; i < ERROR_VECTOR_MAX; i++) { | ||
419 | offset = i * SYNDROME_FRAGMENT_REG_SIZE; | ||
420 | switch (bch_type) { | ||
421 | case BCH8_ECC: | ||
422 | regs->elm_syndrome_fragment_3[i] = elm_read_reg(info, | ||
423 | ELM_SYNDROME_FRAGMENT_3 + offset); | ||
424 | regs->elm_syndrome_fragment_2[i] = elm_read_reg(info, | ||
425 | ELM_SYNDROME_FRAGMENT_2 + offset); | ||
426 | case BCH4_ECC: | ||
427 | regs->elm_syndrome_fragment_1[i] = elm_read_reg(info, | ||
428 | ELM_SYNDROME_FRAGMENT_1 + offset); | ||
429 | regs->elm_syndrome_fragment_0[i] = elm_read_reg(info, | ||
430 | ELM_SYNDROME_FRAGMENT_0 + offset); | ||
431 | default: | ||
432 | return -EINVAL; | ||
433 | } | ||
434 | /* ELM SYNDROME_VALID bit in SYNDROME_FRAGMENT_6[] needs | ||
435 | * to be saved for all BCH schemes*/ | ||
436 | regs->elm_syndrome_fragment_6[i] = elm_read_reg(info, | ||
437 | ELM_SYNDROME_FRAGMENT_6 + offset); | ||
438 | } | ||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | /** | ||
443 | * elm_context_restore | ||
444 | * writes configurations saved duing power-down back into ELM registers | ||
445 | */ | ||
446 | static int elm_context_restore(struct elm_info *info) | ||
447 | { | ||
448 | struct elm_registers *regs = &info->elm_regs; | ||
449 | enum bch_ecc bch_type = info->bch_type; | ||
450 | u32 offset = 0, i; | ||
451 | |||
452 | elm_write_reg(info, ELM_IRQENABLE, regs->elm_irqenable); | ||
453 | elm_write_reg(info, ELM_SYSCONFIG, regs->elm_sysconfig); | ||
454 | elm_write_reg(info, ELM_LOCATION_CONFIG, regs->elm_location_config); | ||
455 | elm_write_reg(info, ELM_PAGE_CTRL, regs->elm_page_ctrl); | ||
456 | for (i = 0; i < ERROR_VECTOR_MAX; i++) { | ||
457 | offset = i * SYNDROME_FRAGMENT_REG_SIZE; | ||
458 | switch (bch_type) { | ||
459 | case BCH8_ECC: | ||
460 | elm_write_reg(info, ELM_SYNDROME_FRAGMENT_3 + offset, | ||
461 | regs->elm_syndrome_fragment_3[i]); | ||
462 | elm_write_reg(info, ELM_SYNDROME_FRAGMENT_2 + offset, | ||
463 | regs->elm_syndrome_fragment_2[i]); | ||
464 | case BCH4_ECC: | ||
465 | elm_write_reg(info, ELM_SYNDROME_FRAGMENT_1 + offset, | ||
466 | regs->elm_syndrome_fragment_1[i]); | ||
467 | elm_write_reg(info, ELM_SYNDROME_FRAGMENT_0 + offset, | ||
468 | regs->elm_syndrome_fragment_0[i]); | ||
469 | default: | ||
470 | return -EINVAL; | ||
471 | } | ||
472 | /* ELM_SYNDROME_VALID bit to be set in last to trigger FSM */ | ||
473 | elm_write_reg(info, ELM_SYNDROME_FRAGMENT_6 + offset, | ||
474 | regs->elm_syndrome_fragment_6[i] & | ||
475 | ELM_SYNDROME_VALID); | ||
476 | } | ||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | static int elm_suspend(struct device *dev) | ||
481 | { | ||
482 | struct elm_info *info = dev_get_drvdata(dev); | ||
483 | elm_context_save(info); | ||
484 | pm_runtime_put_sync(dev); | ||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | static int elm_resume(struct device *dev) | ||
489 | { | ||
490 | struct elm_info *info = dev_get_drvdata(dev); | ||
491 | pm_runtime_get_sync(dev); | ||
492 | elm_context_restore(info); | ||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | static SIMPLE_DEV_PM_OPS(elm_pm_ops, elm_suspend, elm_resume); | ||
497 | |||
388 | #ifdef CONFIG_OF | 498 | #ifdef CONFIG_OF |
389 | static const struct of_device_id elm_of_match[] = { | 499 | static const struct of_device_id elm_of_match[] = { |
390 | { .compatible = "ti,am3352-elm" }, | 500 | { .compatible = "ti,am3352-elm" }, |
@@ -398,6 +508,7 @@ static struct platform_driver elm_driver = { | |||
398 | .name = "elm", | 508 | .name = "elm", |
399 | .owner = THIS_MODULE, | 509 | .owner = THIS_MODULE, |
400 | .of_match_table = of_match_ptr(elm_of_match), | 510 | .of_match_table = of_match_ptr(elm_of_match), |
511 | .pm = &elm_pm_ops, | ||
401 | }, | 512 | }, |
402 | .probe = elm_probe, | 513 | .probe = elm_probe, |
403 | .remove = elm_remove, | 514 | .remove = elm_remove, |
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 2f3d2a5ff349..26b14f9fcac6 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -43,17 +43,24 @@ | |||
43 | #define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */ | 43 | #define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */ |
44 | #define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */ | 44 | #define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */ |
45 | #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ | 45 | #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ |
46 | #define OPCODE_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */ | ||
46 | #define OPCODE_BE_32K 0x52 /* Erase 32KiB block */ | 47 | #define OPCODE_BE_32K 0x52 /* Erase 32KiB block */ |
47 | #define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */ | 48 | #define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */ |
48 | #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ | 49 | #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ |
49 | #define OPCODE_RDID 0x9f /* Read JEDEC ID */ | 50 | #define OPCODE_RDID 0x9f /* Read JEDEC ID */ |
50 | 51 | ||
52 | /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ | ||
53 | #define OPCODE_NORM_READ_4B 0x13 /* Read data bytes (low frequency) */ | ||
54 | #define OPCODE_FAST_READ_4B 0x0c /* Read data bytes (high frequency) */ | ||
55 | #define OPCODE_PP_4B 0x12 /* Page program (up to 256 bytes) */ | ||
56 | #define OPCODE_SE_4B 0xdc /* Sector erase (usually 64KiB) */ | ||
57 | |||
51 | /* Used for SST flashes only. */ | 58 | /* Used for SST flashes only. */ |
52 | #define OPCODE_BP 0x02 /* Byte program */ | 59 | #define OPCODE_BP 0x02 /* Byte program */ |
53 | #define OPCODE_WRDI 0x04 /* Write disable */ | 60 | #define OPCODE_WRDI 0x04 /* Write disable */ |
54 | #define OPCODE_AAI_WP 0xad /* Auto address increment word program */ | 61 | #define OPCODE_AAI_WP 0xad /* Auto address increment word program */ |
55 | 62 | ||
56 | /* Used for Macronix flashes only. */ | 63 | /* Used for Macronix and Winbond flashes. */ |
57 | #define OPCODE_EN4B 0xb7 /* Enter 4-byte mode */ | 64 | #define OPCODE_EN4B 0xb7 /* Enter 4-byte mode */ |
58 | #define OPCODE_EX4B 0xe9 /* Exit 4-byte mode */ | 65 | #define OPCODE_EX4B 0xe9 /* Exit 4-byte mode */ |
59 | 66 | ||
@@ -84,6 +91,8 @@ struct m25p { | |||
84 | u16 page_size; | 91 | u16 page_size; |
85 | u16 addr_width; | 92 | u16 addr_width; |
86 | u8 erase_opcode; | 93 | u8 erase_opcode; |
94 | u8 read_opcode; | ||
95 | u8 program_opcode; | ||
87 | u8 *command; | 96 | u8 *command; |
88 | bool fast_read; | 97 | bool fast_read; |
89 | }; | 98 | }; |
@@ -161,6 +170,7 @@ static inline int set_4byte(struct m25p *flash, u32 jedec_id, int enable) | |||
161 | { | 170 | { |
162 | switch (JEDEC_MFR(jedec_id)) { | 171 | switch (JEDEC_MFR(jedec_id)) { |
163 | case CFI_MFR_MACRONIX: | 172 | case CFI_MFR_MACRONIX: |
173 | case CFI_MFR_ST: /* Micron, actually */ | ||
164 | case 0xEF /* winbond */: | 174 | case 0xEF /* winbond */: |
165 | flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B; | 175 | flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B; |
166 | return spi_write(flash->spi, flash->command, 1); | 176 | return spi_write(flash->spi, flash->command, 1); |
@@ -371,7 +381,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
371 | */ | 381 | */ |
372 | 382 | ||
373 | /* Set up the write data buffer. */ | 383 | /* Set up the write data buffer. */ |
374 | opcode = flash->fast_read ? OPCODE_FAST_READ : OPCODE_NORM_READ; | 384 | opcode = flash->read_opcode; |
375 | flash->command[0] = opcode; | 385 | flash->command[0] = opcode; |
376 | m25p_addr2cmd(flash, from, flash->command); | 386 | m25p_addr2cmd(flash, from, flash->command); |
377 | 387 | ||
@@ -422,7 +432,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
422 | write_enable(flash); | 432 | write_enable(flash); |
423 | 433 | ||
424 | /* Set up the opcode in the write buffer. */ | 434 | /* Set up the opcode in the write buffer. */ |
425 | flash->command[0] = OPCODE_PP; | 435 | flash->command[0] = flash->program_opcode; |
426 | m25p_addr2cmd(flash, to, flash->command); | 436 | m25p_addr2cmd(flash, to, flash->command); |
427 | 437 | ||
428 | page_offset = to & (flash->page_size - 1); | 438 | page_offset = to & (flash->page_size - 1); |
@@ -682,6 +692,8 @@ struct flash_info { | |||
682 | #define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */ | 692 | #define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */ |
683 | #define M25P_NO_ERASE 0x02 /* No erase command needed */ | 693 | #define M25P_NO_ERASE 0x02 /* No erase command needed */ |
684 | #define SST_WRITE 0x04 /* use SST byte programming */ | 694 | #define SST_WRITE 0x04 /* use SST byte programming */ |
695 | #define M25P_NO_FR 0x08 /* Can't do fastread */ | ||
696 | #define SECT_4K_PMC 0x10 /* OPCODE_BE_4K_PMC works uniformly */ | ||
685 | }; | 697 | }; |
686 | 698 | ||
687 | #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ | 699 | #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ |
@@ -694,13 +706,13 @@ struct flash_info { | |||
694 | .flags = (_flags), \ | 706 | .flags = (_flags), \ |
695 | }) | 707 | }) |
696 | 708 | ||
697 | #define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width) \ | 709 | #define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width, _flags) \ |
698 | ((kernel_ulong_t)&(struct flash_info) { \ | 710 | ((kernel_ulong_t)&(struct flash_info) { \ |
699 | .sector_size = (_sector_size), \ | 711 | .sector_size = (_sector_size), \ |
700 | .n_sectors = (_n_sectors), \ | 712 | .n_sectors = (_n_sectors), \ |
701 | .page_size = (_page_size), \ | 713 | .page_size = (_page_size), \ |
702 | .addr_width = (_addr_width), \ | 714 | .addr_width = (_addr_width), \ |
703 | .flags = M25P_NO_ERASE, \ | 715 | .flags = (_flags), \ |
704 | }) | 716 | }) |
705 | 717 | ||
706 | /* NOTE: double check command sets and memory organization when you add | 718 | /* NOTE: double check command sets and memory organization when you add |
@@ -732,7 +744,8 @@ static const struct spi_device_id m25p_ids[] = { | |||
732 | { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) }, | 744 | { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) }, |
733 | 745 | ||
734 | /* Everspin */ | 746 | /* Everspin */ |
735 | { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2) }, | 747 | { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, M25P_NO_ERASE | M25P_NO_FR) }, |
748 | { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, M25P_NO_ERASE | M25P_NO_FR) }, | ||
736 | 749 | ||
737 | /* GigaDevice */ | 750 | /* GigaDevice */ |
738 | { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, | 751 | { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, |
@@ -762,6 +775,11 @@ static const struct spi_device_id m25p_ids[] = { | |||
762 | { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, | 775 | { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, |
763 | { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) }, | 776 | { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) }, |
764 | 777 | ||
778 | /* PMC */ | ||
779 | { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, | ||
780 | { "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) }, | ||
781 | { "pm25lq032", INFO(0x7f9d46, 0, 64 * 1024, 64, SECT_4K) }, | ||
782 | |||
765 | /* Spansion -- single (large) sector size only, at least | 783 | /* Spansion -- single (large) sector size only, at least |
766 | * for the chips listed here (without boot sectors). | 784 | * for the chips listed here (without boot sectors). |
767 | */ | 785 | */ |
@@ -840,17 +858,18 @@ static const struct spi_device_id m25p_ids[] = { | |||
840 | { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, SECT_4K) }, | 858 | { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, SECT_4K) }, |
841 | { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, | 859 | { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, |
842 | { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, | 860 | { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, |
861 | { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, | ||
843 | { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, | 862 | { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, |
844 | { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, | 863 | { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, |
845 | { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, | 864 | { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, |
846 | { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) }, | 865 | { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) }, |
847 | 866 | ||
848 | /* Catalyst / On Semiconductor -- non-JEDEC */ | 867 | /* Catalyst / On Semiconductor -- non-JEDEC */ |
849 | { "cat25c11", CAT25_INFO( 16, 8, 16, 1) }, | 868 | { "cat25c11", CAT25_INFO( 16, 8, 16, 1, M25P_NO_ERASE | M25P_NO_FR) }, |
850 | { "cat25c03", CAT25_INFO( 32, 8, 16, 2) }, | 869 | { "cat25c03", CAT25_INFO( 32, 8, 16, 2, M25P_NO_ERASE | M25P_NO_FR) }, |
851 | { "cat25c09", CAT25_INFO( 128, 8, 32, 2) }, | 870 | { "cat25c09", CAT25_INFO( 128, 8, 32, 2, M25P_NO_ERASE | M25P_NO_FR) }, |
852 | { "cat25c17", CAT25_INFO( 256, 8, 32, 2) }, | 871 | { "cat25c17", CAT25_INFO( 256, 8, 32, 2, M25P_NO_ERASE | M25P_NO_FR) }, |
853 | { "cat25128", CAT25_INFO(2048, 8, 64, 2) }, | 872 | { "cat25128", CAT25_INFO(2048, 8, 64, 2, M25P_NO_ERASE | M25P_NO_FR) }, |
854 | { }, | 873 | { }, |
855 | }; | 874 | }; |
856 | MODULE_DEVICE_TABLE(spi, m25p_ids); | 875 | MODULE_DEVICE_TABLE(spi, m25p_ids); |
@@ -920,7 +939,7 @@ static int m25p_probe(struct spi_device *spi) | |||
920 | * a chip ID, try the JEDEC id commands; they'll work for most | 939 | * a chip ID, try the JEDEC id commands; they'll work for most |
921 | * newer chips, even if we don't recognize the particular chip. | 940 | * newer chips, even if we don't recognize the particular chip. |
922 | */ | 941 | */ |
923 | data = spi->dev.platform_data; | 942 | data = dev_get_platdata(&spi->dev); |
924 | if (data && data->type) { | 943 | if (data && data->type) { |
925 | const struct spi_device_id *plat_id; | 944 | const struct spi_device_id *plat_id; |
926 | 945 | ||
@@ -972,7 +991,7 @@ static int m25p_probe(struct spi_device *spi) | |||
972 | 991 | ||
973 | flash->spi = spi; | 992 | flash->spi = spi; |
974 | mutex_init(&flash->lock); | 993 | mutex_init(&flash->lock); |
975 | dev_set_drvdata(&spi->dev, flash); | 994 | spi_set_drvdata(spi, flash); |
976 | 995 | ||
977 | /* | 996 | /* |
978 | * Atmel, SST and Intel/Numonyx serial flash tend to power | 997 | * Atmel, SST and Intel/Numonyx serial flash tend to power |
@@ -1014,6 +1033,9 @@ static int m25p_probe(struct spi_device *spi) | |||
1014 | if (info->flags & SECT_4K) { | 1033 | if (info->flags & SECT_4K) { |
1015 | flash->erase_opcode = OPCODE_BE_4K; | 1034 | flash->erase_opcode = OPCODE_BE_4K; |
1016 | flash->mtd.erasesize = 4096; | 1035 | flash->mtd.erasesize = 4096; |
1036 | } else if (info->flags & SECT_4K_PMC) { | ||
1037 | flash->erase_opcode = OPCODE_BE_4K_PMC; | ||
1038 | flash->mtd.erasesize = 4096; | ||
1017 | } else { | 1039 | } else { |
1018 | flash->erase_opcode = OPCODE_SE; | 1040 | flash->erase_opcode = OPCODE_SE; |
1019 | flash->mtd.erasesize = info->sector_size; | 1041 | flash->mtd.erasesize = info->sector_size; |
@@ -1028,24 +1050,41 @@ static int m25p_probe(struct spi_device *spi) | |||
1028 | flash->mtd.writebufsize = flash->page_size; | 1050 | flash->mtd.writebufsize = flash->page_size; |
1029 | 1051 | ||
1030 | flash->fast_read = false; | 1052 | flash->fast_read = false; |
1031 | #ifdef CONFIG_OF | ||
1032 | if (np && of_property_read_bool(np, "m25p,fast-read")) | 1053 | if (np && of_property_read_bool(np, "m25p,fast-read")) |
1033 | flash->fast_read = true; | 1054 | flash->fast_read = true; |
1034 | #endif | ||
1035 | 1055 | ||
1036 | #ifdef CONFIG_M25PXX_USE_FAST_READ | 1056 | #ifdef CONFIG_M25PXX_USE_FAST_READ |
1037 | flash->fast_read = true; | 1057 | flash->fast_read = true; |
1038 | #endif | 1058 | #endif |
1059 | if (info->flags & M25P_NO_FR) | ||
1060 | flash->fast_read = false; | ||
1061 | |||
1062 | /* Default commands */ | ||
1063 | if (flash->fast_read) | ||
1064 | flash->read_opcode = OPCODE_FAST_READ; | ||
1065 | else | ||
1066 | flash->read_opcode = OPCODE_NORM_READ; | ||
1067 | |||
1068 | flash->program_opcode = OPCODE_PP; | ||
1039 | 1069 | ||
1040 | if (info->addr_width) | 1070 | if (info->addr_width) |
1041 | flash->addr_width = info->addr_width; | 1071 | flash->addr_width = info->addr_width; |
1042 | else { | 1072 | else if (flash->mtd.size > 0x1000000) { |
1043 | /* enable 4-byte addressing if the device exceeds 16MiB */ | 1073 | /* enable 4-byte addressing if the device exceeds 16MiB */ |
1044 | if (flash->mtd.size > 0x1000000) { | 1074 | flash->addr_width = 4; |
1045 | flash->addr_width = 4; | 1075 | if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) { |
1046 | set_4byte(flash, info->jedec_id, 1); | 1076 | /* Dedicated 4-byte command set */ |
1077 | flash->read_opcode = flash->fast_read ? | ||
1078 | OPCODE_FAST_READ_4B : | ||
1079 | OPCODE_NORM_READ_4B; | ||
1080 | flash->program_opcode = OPCODE_PP_4B; | ||
1081 | /* No small sector erase for 4-byte command set */ | ||
1082 | flash->erase_opcode = OPCODE_SE_4B; | ||
1083 | flash->mtd.erasesize = info->sector_size; | ||
1047 | } else | 1084 | } else |
1048 | flash->addr_width = 3; | 1085 | set_4byte(flash, info->jedec_id, 1); |
1086 | } else { | ||
1087 | flash->addr_width = 3; | ||
1049 | } | 1088 | } |
1050 | 1089 | ||
1051 | dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name, | 1090 | dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name, |
@@ -1080,7 +1119,7 @@ static int m25p_probe(struct spi_device *spi) | |||
1080 | 1119 | ||
1081 | static int m25p_remove(struct spi_device *spi) | 1120 | static int m25p_remove(struct spi_device *spi) |
1082 | { | 1121 | { |
1083 | struct m25p *flash = dev_get_drvdata(&spi->dev); | 1122 | struct m25p *flash = spi_get_drvdata(spi); |
1084 | int status; | 1123 | int status; |
1085 | 1124 | ||
1086 | /* Clean up MTD stuff. */ | 1125 | /* Clean up MTD stuff. */ |
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index 28779b6dfcd9..0e8cbfeba11e 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c | |||
@@ -622,7 +622,7 @@ static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages, | |||
622 | struct dataflash *priv; | 622 | struct dataflash *priv; |
623 | struct mtd_info *device; | 623 | struct mtd_info *device; |
624 | struct mtd_part_parser_data ppdata; | 624 | struct mtd_part_parser_data ppdata; |
625 | struct flash_platform_data *pdata = spi->dev.platform_data; | 625 | struct flash_platform_data *pdata = dev_get_platdata(&spi->dev); |
626 | char *otp_tag = ""; | 626 | char *otp_tag = ""; |
627 | int err = 0; | 627 | int err = 0; |
628 | 628 | ||
@@ -661,7 +661,7 @@ static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages, | |||
661 | dev_info(&spi->dev, "%s (%lld KBytes) pagesize %d bytes%s\n", | 661 | dev_info(&spi->dev, "%s (%lld KBytes) pagesize %d bytes%s\n", |
662 | name, (long long)((device->size + 1023) >> 10), | 662 | name, (long long)((device->size + 1023) >> 10), |
663 | pagesize, otp_tag); | 663 | pagesize, otp_tag); |
664 | dev_set_drvdata(&spi->dev, priv); | 664 | spi_set_drvdata(spi, priv); |
665 | 665 | ||
666 | ppdata.of_node = spi->dev.of_node; | 666 | ppdata.of_node = spi->dev.of_node; |
667 | err = mtd_device_parse_register(device, NULL, &ppdata, | 667 | err = mtd_device_parse_register(device, NULL, &ppdata, |
@@ -671,7 +671,7 @@ static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages, | |||
671 | if (!err) | 671 | if (!err) |
672 | return 0; | 672 | return 0; |
673 | 673 | ||
674 | dev_set_drvdata(&spi->dev, NULL); | 674 | spi_set_drvdata(spi, NULL); |
675 | kfree(priv); | 675 | kfree(priv); |
676 | return err; | 676 | return err; |
677 | } | 677 | } |
@@ -895,14 +895,14 @@ static int dataflash_probe(struct spi_device *spi) | |||
895 | 895 | ||
896 | static int dataflash_remove(struct spi_device *spi) | 896 | static int dataflash_remove(struct spi_device *spi) |
897 | { | 897 | { |
898 | struct dataflash *flash = dev_get_drvdata(&spi->dev); | 898 | struct dataflash *flash = spi_get_drvdata(spi); |
899 | int status; | 899 | int status; |
900 | 900 | ||
901 | pr_debug("%s: remove\n", dev_name(&spi->dev)); | 901 | pr_debug("%s: remove\n", dev_name(&spi->dev)); |
902 | 902 | ||
903 | status = mtd_device_unregister(&flash->mtd); | 903 | status = mtd_device_unregister(&flash->mtd); |
904 | if (status == 0) { | 904 | if (status == 0) { |
905 | dev_set_drvdata(&spi->dev, NULL); | 905 | spi_set_drvdata(spi, NULL); |
906 | kfree(flash); | 906 | kfree(flash); |
907 | } | 907 | } |
908 | return status; | 908 | return status; |
diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c index 8a82b8bc21e1..423821412062 100644 --- a/drivers/mtd/devices/spear_smi.c +++ b/drivers/mtd/devices/spear_smi.c | |||
@@ -550,7 +550,7 @@ static int spear_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
550 | { | 550 | { |
551 | struct spear_snor_flash *flash = get_flash_data(mtd); | 551 | struct spear_snor_flash *flash = get_flash_data(mtd); |
552 | struct spear_smi *dev = mtd->priv; | 552 | struct spear_smi *dev = mtd->priv; |
553 | void *src; | 553 | void __iomem *src; |
554 | u32 ctrlreg1, val; | 554 | u32 ctrlreg1, val; |
555 | int ret; | 555 | int ret; |
556 | 556 | ||
@@ -583,7 +583,7 @@ static int spear_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
583 | 583 | ||
584 | writel(val, dev->io_base + SMI_CR1); | 584 | writel(val, dev->io_base + SMI_CR1); |
585 | 585 | ||
586 | memcpy_fromio(buf, (u8 *)src, len); | 586 | memcpy_fromio(buf, src, len); |
587 | 587 | ||
588 | /* restore ctrl reg1 */ | 588 | /* restore ctrl reg1 */ |
589 | writel(ctrlreg1, dev->io_base + SMI_CR1); | 589 | writel(ctrlreg1, dev->io_base + SMI_CR1); |
@@ -596,7 +596,7 @@ static int spear_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
596 | } | 596 | } |
597 | 597 | ||
598 | static inline int spear_smi_cpy_toio(struct spear_smi *dev, u32 bank, | 598 | static inline int spear_smi_cpy_toio(struct spear_smi *dev, u32 bank, |
599 | void *dest, const void *src, size_t len) | 599 | void __iomem *dest, const void *src, size_t len) |
600 | { | 600 | { |
601 | int ret; | 601 | int ret; |
602 | u32 ctrlreg1; | 602 | u32 ctrlreg1; |
@@ -643,7 +643,7 @@ static int spear_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
643 | { | 643 | { |
644 | struct spear_snor_flash *flash = get_flash_data(mtd); | 644 | struct spear_snor_flash *flash = get_flash_data(mtd); |
645 | struct spear_smi *dev = mtd->priv; | 645 | struct spear_smi *dev = mtd->priv; |
646 | void *dest; | 646 | void __iomem *dest; |
647 | u32 page_offset, page_size; | 647 | u32 page_offset, page_size; |
648 | int ret; | 648 | int ret; |
649 | 649 | ||
@@ -995,14 +995,12 @@ static int spear_smi_probe(struct platform_device *pdev) | |||
995 | ret = spear_smi_setup_banks(pdev, i, pdata->np[i]); | 995 | ret = spear_smi_setup_banks(pdev, i, pdata->np[i]); |
996 | if (ret) { | 996 | if (ret) { |
997 | dev_err(&dev->pdev->dev, "bank setup failed\n"); | 997 | dev_err(&dev->pdev->dev, "bank setup failed\n"); |
998 | goto err_bank_setup; | 998 | goto err_irq; |
999 | } | 999 | } |
1000 | } | 1000 | } |
1001 | 1001 | ||
1002 | return 0; | 1002 | return 0; |
1003 | 1003 | ||
1004 | err_bank_setup: | ||
1005 | platform_set_drvdata(pdev, NULL); | ||
1006 | err_irq: | 1004 | err_irq: |
1007 | clk_disable_unprepare(dev->clk); | 1005 | clk_disable_unprepare(dev->clk); |
1008 | err: | 1006 | err: |
@@ -1040,12 +1038,11 @@ static int spear_smi_remove(struct platform_device *pdev) | |||
1040 | } | 1038 | } |
1041 | 1039 | ||
1042 | clk_disable_unprepare(dev->clk); | 1040 | clk_disable_unprepare(dev->clk); |
1043 | platform_set_drvdata(pdev, NULL); | ||
1044 | 1041 | ||
1045 | return 0; | 1042 | return 0; |
1046 | } | 1043 | } |
1047 | 1044 | ||
1048 | #ifdef CONFIG_PM | 1045 | #ifdef CONFIG_PM_SLEEP |
1049 | static int spear_smi_suspend(struct device *dev) | 1046 | static int spear_smi_suspend(struct device *dev) |
1050 | { | 1047 | { |
1051 | struct spear_smi *sdev = dev_get_drvdata(dev); | 1048 | struct spear_smi *sdev = dev_get_drvdata(dev); |
@@ -1068,9 +1065,9 @@ static int spear_smi_resume(struct device *dev) | |||
1068 | spear_smi_hw_init(sdev); | 1065 | spear_smi_hw_init(sdev); |
1069 | return ret; | 1066 | return ret; |
1070 | } | 1067 | } |
1068 | #endif | ||
1071 | 1069 | ||
1072 | static SIMPLE_DEV_PM_OPS(spear_smi_pm_ops, spear_smi_suspend, spear_smi_resume); | 1070 | static SIMPLE_DEV_PM_OPS(spear_smi_pm_ops, spear_smi_suspend, spear_smi_resume); |
1073 | #endif | ||
1074 | 1071 | ||
1075 | #ifdef CONFIG_OF | 1072 | #ifdef CONFIG_OF |
1076 | static const struct of_device_id spear_smi_id_table[] = { | 1073 | static const struct of_device_id spear_smi_id_table[] = { |
@@ -1086,9 +1083,7 @@ static struct platform_driver spear_smi_driver = { | |||
1086 | .bus = &platform_bus_type, | 1083 | .bus = &platform_bus_type, |
1087 | .owner = THIS_MODULE, | 1084 | .owner = THIS_MODULE, |
1088 | .of_match_table = of_match_ptr(spear_smi_id_table), | 1085 | .of_match_table = of_match_ptr(spear_smi_id_table), |
1089 | #ifdef CONFIG_PM | ||
1090 | .pm = &spear_smi_pm_ops, | 1086 | .pm = &spear_smi_pm_ops, |
1091 | #endif | ||
1092 | }, | 1087 | }, |
1093 | .probe = spear_smi_probe, | 1088 | .probe = spear_smi_probe, |
1094 | .remove = spear_smi_remove, | 1089 | .remove = spear_smi_remove, |
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c index 8091b0163694..a42f1f0e7281 100644 --- a/drivers/mtd/devices/sst25l.c +++ b/drivers/mtd/devices/sst25l.c | |||
@@ -370,9 +370,9 @@ static int sst25l_probe(struct spi_device *spi) | |||
370 | 370 | ||
371 | flash->spi = spi; | 371 | flash->spi = spi; |
372 | mutex_init(&flash->lock); | 372 | mutex_init(&flash->lock); |
373 | dev_set_drvdata(&spi->dev, flash); | 373 | spi_set_drvdata(spi, flash); |
374 | 374 | ||
375 | data = spi->dev.platform_data; | 375 | data = dev_get_platdata(&spi->dev); |
376 | if (data && data->name) | 376 | if (data && data->name) |
377 | flash->mtd.name = data->name; | 377 | flash->mtd.name = data->name; |
378 | else | 378 | else |
@@ -404,7 +404,7 @@ static int sst25l_probe(struct spi_device *spi) | |||
404 | data ? data->nr_parts : 0); | 404 | data ? data->nr_parts : 0); |
405 | if (ret) { | 405 | if (ret) { |
406 | kfree(flash); | 406 | kfree(flash); |
407 | dev_set_drvdata(&spi->dev, NULL); | 407 | spi_set_drvdata(spi, NULL); |
408 | return -ENODEV; | 408 | return -ENODEV; |
409 | } | 409 | } |
410 | 410 | ||
@@ -413,7 +413,7 @@ static int sst25l_probe(struct spi_device *spi) | |||
413 | 413 | ||
414 | static int sst25l_remove(struct spi_device *spi) | 414 | static int sst25l_remove(struct spi_device *spi) |
415 | { | 415 | { |
416 | struct sst25l_flash *flash = dev_get_drvdata(&spi->dev); | 416 | struct sst25l_flash *flash = spi_get_drvdata(spi); |
417 | int ret; | 417 | int ret; |
418 | 418 | ||
419 | ret = mtd_device_unregister(&flash->mtd); | 419 | ret = mtd_device_unregister(&flash->mtd); |
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 8b27ca054c59..310dc7c93425 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
@@ -157,24 +157,6 @@ config MTD_PXA2XX | |||
157 | help | 157 | help |
158 | This provides a driver for the NOR flash attached to a PXA2xx chip. | 158 | This provides a driver for the NOR flash attached to a PXA2xx chip. |
159 | 159 | ||
160 | config MTD_OCTAGON | ||
161 | tristate "JEDEC Flash device mapped on Octagon 5066 SBC" | ||
162 | depends on X86 && MTD_JEDEC && MTD_COMPLEX_MAPPINGS | ||
163 | help | ||
164 | This provides a 'mapping' driver which supports the way in which | ||
165 | the flash chips are connected in the Octagon-5066 Single Board | ||
166 | Computer. More information on the board is available at | ||
167 | <http://www.octagonsystems.com/products/5066.aspx>. | ||
168 | |||
169 | config MTD_VMAX | ||
170 | tristate "JEDEC Flash device mapped on Tempustech VMAX SBC301" | ||
171 | depends on X86 && MTD_JEDEC && MTD_COMPLEX_MAPPINGS | ||
172 | help | ||
173 | This provides a 'mapping' driver which supports the way in which | ||
174 | the flash chips are connected in the Tempustech VMAX SBC301 Single | ||
175 | Board Computer. More information on the board is available at | ||
176 | <http://www.tempustech.com/>. | ||
177 | |||
178 | config MTD_SCx200_DOCFLASH | 160 | config MTD_SCx200_DOCFLASH |
179 | tristate "Flash device mapped with DOCCS on NatSemi SCx200" | 161 | tristate "Flash device mapped with DOCCS on NatSemi SCx200" |
180 | depends on SCx200 && MTD_CFI | 162 | depends on SCx200 && MTD_CFI |
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index 9fdbd4ba6441..141c91a5b24c 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile | |||
@@ -16,7 +16,6 @@ obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o | |||
16 | obj-$(CONFIG_MTD_CK804XROM) += ck804xrom.o | 16 | obj-$(CONFIG_MTD_CK804XROM) += ck804xrom.o |
17 | obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o | 17 | obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o |
18 | obj-$(CONFIG_MTD_PXA2XX) += pxa2xx-flash.o | 18 | obj-$(CONFIG_MTD_PXA2XX) += pxa2xx-flash.o |
19 | obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o | ||
20 | obj-$(CONFIG_MTD_PHYSMAP) += physmap.o | 19 | obj-$(CONFIG_MTD_PHYSMAP) += physmap.o |
21 | obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o | 20 | obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o |
22 | obj-$(CONFIG_MTD_PISMO) += pismo.o | 21 | obj-$(CONFIG_MTD_PISMO) += pismo.o |
@@ -28,7 +27,6 @@ obj-$(CONFIG_MTD_SC520CDP) += sc520cdp.o | |||
28 | obj-$(CONFIG_MTD_NETSC520) += netsc520.o | 27 | obj-$(CONFIG_MTD_NETSC520) += netsc520.o |
29 | obj-$(CONFIG_MTD_TS5500) += ts5500_flash.o | 28 | obj-$(CONFIG_MTD_TS5500) += ts5500_flash.o |
30 | obj-$(CONFIG_MTD_SUN_UFLASH) += sun_uflash.o | 29 | obj-$(CONFIG_MTD_SUN_UFLASH) += sun_uflash.o |
31 | obj-$(CONFIG_MTD_VMAX) += vmax301.o | ||
32 | obj-$(CONFIG_MTD_SCx200_DOCFLASH)+= scx200_docflash.o | 30 | obj-$(CONFIG_MTD_SCx200_DOCFLASH)+= scx200_docflash.o |
33 | obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o | 31 | obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o |
34 | obj-$(CONFIG_MTD_PCI) += pci.o | 32 | obj-$(CONFIG_MTD_PCI) += pci.o |
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c index 319b04a6c9d1..5434d8ded015 100644 --- a/drivers/mtd/maps/bfin-async-flash.c +++ b/drivers/mtd/maps/bfin-async-flash.c | |||
@@ -128,7 +128,7 @@ static const char * const part_probe_types[] = { | |||
128 | static int bfin_flash_probe(struct platform_device *pdev) | 128 | static int bfin_flash_probe(struct platform_device *pdev) |
129 | { | 129 | { |
130 | int ret; | 130 | int ret; |
131 | struct physmap_flash_data *pdata = pdev->dev.platform_data; | 131 | struct physmap_flash_data *pdata = dev_get_platdata(&pdev->dev); |
132 | struct resource *memory = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 132 | struct resource *memory = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
133 | struct resource *flash_ambctl = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 133 | struct resource *flash_ambctl = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
134 | struct async_state *state; | 134 | struct async_state *state; |
diff --git a/drivers/mtd/maps/cfi_flagadm.c b/drivers/mtd/maps/cfi_flagadm.c index d16fc9d3b8cd..d504b3d1791d 100644 --- a/drivers/mtd/maps/cfi_flagadm.c +++ b/drivers/mtd/maps/cfi_flagadm.c | |||
@@ -55,13 +55,13 @@ | |||
55 | #define FLASH_PARTITION3_SIZE 0x001C0000 | 55 | #define FLASH_PARTITION3_SIZE 0x001C0000 |
56 | 56 | ||
57 | 57 | ||
58 | struct map_info flagadm_map = { | 58 | static struct map_info flagadm_map = { |
59 | .name = "FlagaDM flash device", | 59 | .name = "FlagaDM flash device", |
60 | .size = FLASH_SIZE, | 60 | .size = FLASH_SIZE, |
61 | .bankwidth = 2, | 61 | .bankwidth = 2, |
62 | }; | 62 | }; |
63 | 63 | ||
64 | struct mtd_partition flagadm_parts[] = { | 64 | static struct mtd_partition flagadm_parts[] = { |
65 | { | 65 | { |
66 | .name = "Bootloader", | 66 | .name = "Bootloader", |
67 | .offset = FLASH_PARTITION0_ADDR, | 67 | .offset = FLASH_PARTITION0_ADDR, |
@@ -112,7 +112,7 @@ static int __init init_flagadm(void) | |||
112 | return 0; | 112 | return 0; |
113 | } | 113 | } |
114 | 114 | ||
115 | iounmap((void *)flagadm_map.virt); | 115 | iounmap((void __iomem *)flagadm_map.virt); |
116 | return -ENXIO; | 116 | return -ENXIO; |
117 | } | 117 | } |
118 | 118 | ||
@@ -123,8 +123,8 @@ static void __exit cleanup_flagadm(void) | |||
123 | map_destroy(mymtd); | 123 | map_destroy(mymtd); |
124 | } | 124 | } |
125 | if (flagadm_map.virt) { | 125 | if (flagadm_map.virt) { |
126 | iounmap((void *)flagadm_map.virt); | 126 | iounmap((void __iomem *)flagadm_map.virt); |
127 | flagadm_map.virt = 0; | 127 | flagadm_map.virt = NULL; |
128 | } | 128 | } |
129 | } | 129 | } |
130 | 130 | ||
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c index 5ede28294f9e..1adba86474a5 100644 --- a/drivers/mtd/maps/gpio-addr-flash.c +++ b/drivers/mtd/maps/gpio-addr-flash.c | |||
@@ -196,7 +196,7 @@ static int gpio_flash_probe(struct platform_device *pdev) | |||
196 | struct resource *gpios; | 196 | struct resource *gpios; |
197 | struct async_state *state; | 197 | struct async_state *state; |
198 | 198 | ||
199 | pdata = pdev->dev.platform_data; | 199 | pdata = dev_get_platdata(&pdev->dev); |
200 | memory = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 200 | memory = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
201 | gpios = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 201 | gpios = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
202 | 202 | ||
diff --git a/drivers/mtd/maps/impa7.c b/drivers/mtd/maps/impa7.c index 49686744d93c..15bbda03be65 100644 --- a/drivers/mtd/maps/impa7.c +++ b/drivers/mtd/maps/impa7.c | |||
@@ -79,7 +79,7 @@ static int __init init_impa7(void) | |||
79 | } | 79 | } |
80 | simple_map_init(&impa7_map[i]); | 80 | simple_map_init(&impa7_map[i]); |
81 | 81 | ||
82 | impa7_mtd[i] = 0; | 82 | impa7_mtd[i] = NULL; |
83 | type = rom_probe_types; | 83 | type = rom_probe_types; |
84 | for(; !impa7_mtd[i] && *type; type++) { | 84 | for(; !impa7_mtd[i] && *type; type++) { |
85 | impa7_mtd[i] = do_map_probe(*type, &impa7_map[i]); | 85 | impa7_mtd[i] = do_map_probe(*type, &impa7_map[i]); |
@@ -91,9 +91,9 @@ static int __init init_impa7(void) | |||
91 | mtd_device_parse_register(impa7_mtd[i], NULL, NULL, | 91 | mtd_device_parse_register(impa7_mtd[i], NULL, NULL, |
92 | partitions, | 92 | partitions, |
93 | ARRAY_SIZE(partitions)); | 93 | ARRAY_SIZE(partitions)); |
94 | } else { | ||
95 | iounmap((void __iomem *)impa7_map[i].virt); | ||
94 | } | 96 | } |
95 | else | ||
96 | iounmap((void *)impa7_map[i].virt); | ||
97 | } | 97 | } |
98 | return devicesfound == 0 ? -ENXIO : 0; | 98 | return devicesfound == 0 ? -ENXIO : 0; |
99 | } | 99 | } |
@@ -105,8 +105,8 @@ static void __exit cleanup_impa7(void) | |||
105 | if (impa7_mtd[i]) { | 105 | if (impa7_mtd[i]) { |
106 | mtd_device_unregister(impa7_mtd[i]); | 106 | mtd_device_unregister(impa7_mtd[i]); |
107 | map_destroy(impa7_mtd[i]); | 107 | map_destroy(impa7_mtd[i]); |
108 | iounmap((void *)impa7_map[i].virt); | 108 | iounmap((void __iomem *)impa7_map[i].virt); |
109 | impa7_map[i].virt = 0; | 109 | impa7_map[i].virt = NULL; |
110 | } | 110 | } |
111 | } | 111 | } |
112 | } | 112 | } |
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index 52b3410a105c..10debfea81e7 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c | |||
@@ -152,11 +152,9 @@ static const char * const probes[] = { "RedBoot", "cmdlinepart", NULL }; | |||
152 | 152 | ||
153 | static int ixp4xx_flash_remove(struct platform_device *dev) | 153 | static int ixp4xx_flash_remove(struct platform_device *dev) |
154 | { | 154 | { |
155 | struct flash_platform_data *plat = dev->dev.platform_data; | 155 | struct flash_platform_data *plat = dev_get_platdata(&dev->dev); |
156 | struct ixp4xx_flash_info *info = platform_get_drvdata(dev); | 156 | struct ixp4xx_flash_info *info = platform_get_drvdata(dev); |
157 | 157 | ||
158 | platform_set_drvdata(dev, NULL); | ||
159 | |||
160 | if(!info) | 158 | if(!info) |
161 | return 0; | 159 | return 0; |
162 | 160 | ||
@@ -180,7 +178,7 @@ static int ixp4xx_flash_remove(struct platform_device *dev) | |||
180 | 178 | ||
181 | static int ixp4xx_flash_probe(struct platform_device *dev) | 179 | static int ixp4xx_flash_probe(struct platform_device *dev) |
182 | { | 180 | { |
183 | struct flash_platform_data *plat = dev->dev.platform_data; | 181 | struct flash_platform_data *plat = dev_get_platdata(&dev->dev); |
184 | struct ixp4xx_flash_info *info; | 182 | struct ixp4xx_flash_info *info; |
185 | struct mtd_part_parser_data ppdata = { | 183 | struct mtd_part_parser_data ppdata = { |
186 | .origin = dev->resource->start, | 184 | .origin = dev->resource->start, |
diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c index ab0fead56b83..98bb5d5375d7 100644 --- a/drivers/mtd/maps/latch-addr-flash.c +++ b/drivers/mtd/maps/latch-addr-flash.c | |||
@@ -102,9 +102,8 @@ static int latch_addr_flash_remove(struct platform_device *dev) | |||
102 | info = platform_get_drvdata(dev); | 102 | info = platform_get_drvdata(dev); |
103 | if (info == NULL) | 103 | if (info == NULL) |
104 | return 0; | 104 | return 0; |
105 | platform_set_drvdata(dev, NULL); | ||
106 | 105 | ||
107 | latch_addr_data = dev->dev.platform_data; | 106 | latch_addr_data = dev_get_platdata(&dev->dev); |
108 | 107 | ||
109 | if (info->mtd != NULL) { | 108 | if (info->mtd != NULL) { |
110 | mtd_device_unregister(info->mtd); | 109 | mtd_device_unregister(info->mtd); |
@@ -135,7 +134,7 @@ static int latch_addr_flash_probe(struct platform_device *dev) | |||
135 | int chipsel; | 134 | int chipsel; |
136 | int err; | 135 | int err; |
137 | 136 | ||
138 | latch_addr_data = dev->dev.platform_data; | 137 | latch_addr_data = dev_get_platdata(&dev->dev); |
139 | if (latch_addr_data == NULL) | 138 | if (latch_addr_data == NULL) |
140 | return -ENODEV; | 139 | return -ENODEV; |
141 | 140 | ||
diff --git a/drivers/mtd/maps/octagon-5066.c b/drivers/mtd/maps/octagon-5066.c deleted file mode 100644 index 807ac2a2e686..000000000000 --- a/drivers/mtd/maps/octagon-5066.c +++ /dev/null | |||
@@ -1,246 +0,0 @@ | |||
1 | /* ###################################################################### | ||
2 | |||
3 | Octagon 5066 MTD Driver. | ||
4 | |||
5 | The Octagon 5066 is a SBC based on AMD's 586-WB running at 133 MHZ. It | ||
6 | comes with a builtin AMD 29F016 flash chip and a socketed EEPROM that | ||
7 | is replacable by flash. Both units are mapped through a multiplexer | ||
8 | into a 32k memory window at 0xe8000. The control register for the | ||
9 | multiplexing unit is located at IO 0x208 with a bit map of | ||
10 | 0-5 Page Selection in 32k increments | ||
11 | 6-7 Device selection: | ||
12 | 00 SSD off | ||
13 | 01 SSD 0 (Socket) | ||
14 | 10 SSD 1 (Flash chip) | ||
15 | 11 undefined | ||
16 | |||
17 | On each SSD, the first 128k is reserved for use by the bios | ||
18 | (actually it IS the bios..) This only matters if you are booting off the | ||
19 | flash, you must not put a file system starting there. | ||
20 | |||
21 | The driver tries to do a detection algorithm to guess what sort of devices | ||
22 | are plugged into the sockets. | ||
23 | |||
24 | ##################################################################### */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/ioport.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <asm/io.h> | ||
30 | |||
31 | #include <linux/mtd/map.h> | ||
32 | #include <linux/mtd/mtd.h> | ||
33 | |||
34 | #define WINDOW_START 0xe8000 | ||
35 | #define WINDOW_LENGTH 0x8000 | ||
36 | #define WINDOW_SHIFT 27 | ||
37 | #define WINDOW_MASK 0x7FFF | ||
38 | #define PAGE_IO 0x208 | ||
39 | |||
40 | static volatile char page_n_dev = 0; | ||
41 | static unsigned long iomapadr; | ||
42 | static DEFINE_SPINLOCK(oct5066_spin); | ||
43 | |||
44 | /* | ||
45 | * We use map_priv_1 to identify which device we are. | ||
46 | */ | ||
47 | |||
48 | static void __oct5066_page(struct map_info *map, __u8 byte) | ||
49 | { | ||
50 | outb(byte,PAGE_IO); | ||
51 | page_n_dev = byte; | ||
52 | } | ||
53 | |||
54 | static inline void oct5066_page(struct map_info *map, unsigned long ofs) | ||
55 | { | ||
56 | __u8 byte = map->map_priv_1 | (ofs >> WINDOW_SHIFT); | ||
57 | |||
58 | if (page_n_dev != byte) | ||
59 | __oct5066_page(map, byte); | ||
60 | } | ||
61 | |||
62 | |||
63 | static map_word oct5066_read8(struct map_info *map, unsigned long ofs) | ||
64 | { | ||
65 | map_word ret; | ||
66 | spin_lock(&oct5066_spin); | ||
67 | oct5066_page(map, ofs); | ||
68 | ret.x[0] = readb(iomapadr + (ofs & WINDOW_MASK)); | ||
69 | spin_unlock(&oct5066_spin); | ||
70 | return ret; | ||
71 | } | ||
72 | |||
73 | static void oct5066_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) | ||
74 | { | ||
75 | while(len) { | ||
76 | unsigned long thislen = len; | ||
77 | if (len > (WINDOW_LENGTH - (from & WINDOW_MASK))) | ||
78 | thislen = WINDOW_LENGTH-(from & WINDOW_MASK); | ||
79 | |||
80 | spin_lock(&oct5066_spin); | ||
81 | oct5066_page(map, from); | ||
82 | memcpy_fromio(to, iomapadr + from, thislen); | ||
83 | spin_unlock(&oct5066_spin); | ||
84 | to += thislen; | ||
85 | from += thislen; | ||
86 | len -= thislen; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | static void oct5066_write8(struct map_info *map, map_word d, unsigned long adr) | ||
91 | { | ||
92 | spin_lock(&oct5066_spin); | ||
93 | oct5066_page(map, adr); | ||
94 | writeb(d.x[0], iomapadr + (adr & WINDOW_MASK)); | ||
95 | spin_unlock(&oct5066_spin); | ||
96 | } | ||
97 | |||
98 | static void oct5066_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) | ||
99 | { | ||
100 | while(len) { | ||
101 | unsigned long thislen = len; | ||
102 | if (len > (WINDOW_LENGTH - (to & WINDOW_MASK))) | ||
103 | thislen = WINDOW_LENGTH-(to & WINDOW_MASK); | ||
104 | |||
105 | spin_lock(&oct5066_spin); | ||
106 | oct5066_page(map, to); | ||
107 | memcpy_toio(iomapadr + to, from, thislen); | ||
108 | spin_unlock(&oct5066_spin); | ||
109 | to += thislen; | ||
110 | from += thislen; | ||
111 | len -= thislen; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | static struct map_info oct5066_map[2] = { | ||
116 | { | ||
117 | .name = "Octagon 5066 Socket", | ||
118 | .phys = NO_XIP, | ||
119 | .size = 512 * 1024, | ||
120 | .bankwidth = 1, | ||
121 | .read = oct5066_read8, | ||
122 | .copy_from = oct5066_copy_from, | ||
123 | .write = oct5066_write8, | ||
124 | .copy_to = oct5066_copy_to, | ||
125 | .map_priv_1 = 1<<6 | ||
126 | }, | ||
127 | { | ||
128 | .name = "Octagon 5066 Internal Flash", | ||
129 | .phys = NO_XIP, | ||
130 | .size = 2 * 1024 * 1024, | ||
131 | .bankwidth = 1, | ||
132 | .read = oct5066_read8, | ||
133 | .copy_from = oct5066_copy_from, | ||
134 | .write = oct5066_write8, | ||
135 | .copy_to = oct5066_copy_to, | ||
136 | .map_priv_1 = 2<<6 | ||
137 | } | ||
138 | }; | ||
139 | |||
140 | static struct mtd_info *oct5066_mtd[2] = {NULL, NULL}; | ||
141 | |||
142 | // OctProbe - Sense if this is an octagon card | ||
143 | // --------------------------------------------------------------------- | ||
144 | /* Perform a simple validity test, we map the window select SSD0 and | ||
145 | change pages while monitoring the window. A change in the window, | ||
146 | controlled by the PAGE_IO port is a functioning 5066 board. This will | ||
147 | fail if the thing in the socket is set to a uniform value. */ | ||
148 | static int __init OctProbe(void) | ||
149 | { | ||
150 | unsigned int Base = (1 << 6); | ||
151 | unsigned long I; | ||
152 | unsigned long Values[10]; | ||
153 | for (I = 0; I != 20; I++) | ||
154 | { | ||
155 | outb(Base + (I%10),PAGE_IO); | ||
156 | if (I < 10) | ||
157 | { | ||
158 | // Record the value and check for uniqueness | ||
159 | Values[I%10] = readl(iomapadr); | ||
160 | if (I > 0 && Values[I%10] == Values[0]) | ||
161 | return -EAGAIN; | ||
162 | } | ||
163 | else | ||
164 | { | ||
165 | // Make sure we get the same values on the second pass | ||
166 | if (Values[I%10] != readl(iomapadr)) | ||
167 | return -EAGAIN; | ||
168 | } | ||
169 | } | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | void cleanup_oct5066(void) | ||
174 | { | ||
175 | int i; | ||
176 | for (i=0; i<2; i++) { | ||
177 | if (oct5066_mtd[i]) { | ||
178 | mtd_device_unregister(oct5066_mtd[i]); | ||
179 | map_destroy(oct5066_mtd[i]); | ||
180 | } | ||
181 | } | ||
182 | iounmap((void *)iomapadr); | ||
183 | release_region(PAGE_IO, 1); | ||
184 | } | ||
185 | |||
186 | static int __init init_oct5066(void) | ||
187 | { | ||
188 | int i; | ||
189 | int ret = 0; | ||
190 | |||
191 | // Do an autoprobe sequence | ||
192 | if (!request_region(PAGE_IO,1,"Octagon SSD")) { | ||
193 | printk(KERN_NOTICE "5066: Page Register in Use\n"); | ||
194 | return -EAGAIN; | ||
195 | } | ||
196 | iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH); | ||
197 | if (!iomapadr) { | ||
198 | printk(KERN_NOTICE "Failed to ioremap memory region\n"); | ||
199 | ret = -EIO; | ||
200 | goto out_rel; | ||
201 | } | ||
202 | if (OctProbe() != 0) { | ||
203 | printk(KERN_NOTICE "5066: Octagon Probe Failed, is this an Octagon 5066 SBC?\n"); | ||
204 | iounmap((void *)iomapadr); | ||
205 | ret = -EAGAIN; | ||
206 | goto out_unmap; | ||
207 | } | ||
208 | |||
209 | // Print out our little header.. | ||
210 | printk("Octagon 5066 SSD IO:0x%x MEM:0x%x-0x%x\n",PAGE_IO,WINDOW_START, | ||
211 | WINDOW_START+WINDOW_LENGTH); | ||
212 | |||
213 | for (i=0; i<2; i++) { | ||
214 | oct5066_mtd[i] = do_map_probe("cfi_probe", &oct5066_map[i]); | ||
215 | if (!oct5066_mtd[i]) | ||
216 | oct5066_mtd[i] = do_map_probe("jedec", &oct5066_map[i]); | ||
217 | if (!oct5066_mtd[i]) | ||
218 | oct5066_mtd[i] = do_map_probe("map_ram", &oct5066_map[i]); | ||
219 | if (!oct5066_mtd[i]) | ||
220 | oct5066_mtd[i] = do_map_probe("map_rom", &oct5066_map[i]); | ||
221 | if (oct5066_mtd[i]) { | ||
222 | oct5066_mtd[i]->owner = THIS_MODULE; | ||
223 | mtd_device_register(oct5066_mtd[i], NULL, 0); | ||
224 | } | ||
225 | } | ||
226 | |||
227 | if (!oct5066_mtd[0] && !oct5066_mtd[1]) { | ||
228 | cleanup_oct5066(); | ||
229 | return -ENXIO; | ||
230 | } | ||
231 | |||
232 | return 0; | ||
233 | |||
234 | out_unmap: | ||
235 | iounmap((void *)iomapadr); | ||
236 | out_rel: | ||
237 | release_region(PAGE_IO, 1); | ||
238 | return ret; | ||
239 | } | ||
240 | |||
241 | module_init(init_oct5066); | ||
242 | module_exit(cleanup_oct5066); | ||
243 | |||
244 | MODULE_LICENSE("GPL"); | ||
245 | MODULE_AUTHOR("Jason Gunthorpe <jgg@deltatee.com>, David Woodhouse <dwmw2@infradead.org>"); | ||
246 | MODULE_DESCRIPTION("MTD map driver for Octagon 5066 Single Board Computer"); | ||
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index e7a592c8c765..f73cd461257c 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c | |||
@@ -40,9 +40,8 @@ static int physmap_flash_remove(struct platform_device *dev) | |||
40 | info = platform_get_drvdata(dev); | 40 | info = platform_get_drvdata(dev); |
41 | if (info == NULL) | 41 | if (info == NULL) |
42 | return 0; | 42 | return 0; |
43 | platform_set_drvdata(dev, NULL); | ||
44 | 43 | ||
45 | physmap_data = dev->dev.platform_data; | 44 | physmap_data = dev_get_platdata(&dev->dev); |
46 | 45 | ||
47 | if (info->cmtd) { | 46 | if (info->cmtd) { |
48 | mtd_device_unregister(info->cmtd); | 47 | mtd_device_unregister(info->cmtd); |
@@ -69,7 +68,7 @@ static void physmap_set_vpp(struct map_info *map, int state) | |||
69 | unsigned long flags; | 68 | unsigned long flags; |
70 | 69 | ||
71 | pdev = (struct platform_device *)map->map_priv_1; | 70 | pdev = (struct platform_device *)map->map_priv_1; |
72 | physmap_data = pdev->dev.platform_data; | 71 | physmap_data = dev_get_platdata(&pdev->dev); |
73 | 72 | ||
74 | if (!physmap_data->set_vpp) | 73 | if (!physmap_data->set_vpp) |
75 | return; | 74 | return; |
@@ -103,7 +102,7 @@ static int physmap_flash_probe(struct platform_device *dev) | |||
103 | int i; | 102 | int i; |
104 | int devices_found = 0; | 103 | int devices_found = 0; |
105 | 104 | ||
106 | physmap_data = dev->dev.platform_data; | 105 | physmap_data = dev_get_platdata(&dev->dev); |
107 | if (physmap_data == NULL) | 106 | if (physmap_data == NULL) |
108 | return -ENODEV; | 107 | return -ENODEV; |
109 | 108 | ||
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 71fdda29594b..676271659b37 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c | |||
@@ -84,8 +84,6 @@ static int platram_remove(struct platform_device *pdev) | |||
84 | { | 84 | { |
85 | struct platram_info *info = to_platram_info(pdev); | 85 | struct platram_info *info = to_platram_info(pdev); |
86 | 86 | ||
87 | platform_set_drvdata(pdev, NULL); | ||
88 | |||
89 | dev_dbg(&pdev->dev, "removing device\n"); | 87 | dev_dbg(&pdev->dev, "removing device\n"); |
90 | 88 | ||
91 | if (info == NULL) | 89 | if (info == NULL) |
@@ -130,13 +128,13 @@ static int platram_probe(struct platform_device *pdev) | |||
130 | 128 | ||
131 | dev_dbg(&pdev->dev, "probe entered\n"); | 129 | dev_dbg(&pdev->dev, "probe entered\n"); |
132 | 130 | ||
133 | if (pdev->dev.platform_data == NULL) { | 131 | if (dev_get_platdata(&pdev->dev) == NULL) { |
134 | dev_err(&pdev->dev, "no platform data supplied\n"); | 132 | dev_err(&pdev->dev, "no platform data supplied\n"); |
135 | err = -ENOENT; | 133 | err = -ENOENT; |
136 | goto exit_error; | 134 | goto exit_error; |
137 | } | 135 | } |
138 | 136 | ||
139 | pdata = pdev->dev.platform_data; | 137 | pdata = dev_get_platdata(&pdev->dev); |
140 | 138 | ||
141 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 139 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
142 | if (info == NULL) { | 140 | if (info == NULL) { |
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c index acb1dbcf7ce5..d210d131fef2 100644 --- a/drivers/mtd/maps/pxa2xx-flash.c +++ b/drivers/mtd/maps/pxa2xx-flash.c | |||
@@ -49,7 +49,7 @@ static const char * const probes[] = { "RedBoot", "cmdlinepart", NULL }; | |||
49 | 49 | ||
50 | static int pxa2xx_flash_probe(struct platform_device *pdev) | 50 | static int pxa2xx_flash_probe(struct platform_device *pdev) |
51 | { | 51 | { |
52 | struct flash_platform_data *flash = pdev->dev.platform_data; | 52 | struct flash_platform_data *flash = dev_get_platdata(&pdev->dev); |
53 | struct pxa2xx_flash_info *info; | 53 | struct pxa2xx_flash_info *info; |
54 | struct resource *res; | 54 | struct resource *res; |
55 | 55 | ||
@@ -107,8 +107,6 @@ static int pxa2xx_flash_remove(struct platform_device *dev) | |||
107 | { | 107 | { |
108 | struct pxa2xx_flash_info *info = platform_get_drvdata(dev); | 108 | struct pxa2xx_flash_info *info = platform_get_drvdata(dev); |
109 | 109 | ||
110 | platform_set_drvdata(dev, NULL); | ||
111 | |||
112 | mtd_device_unregister(info->mtd); | 110 | mtd_device_unregister(info->mtd); |
113 | 111 | ||
114 | map_destroy(info->mtd); | 112 | map_destroy(info->mtd); |
diff --git a/drivers/mtd/maps/rbtx4939-flash.c b/drivers/mtd/maps/rbtx4939-flash.c index ac02fbffd6df..93525121d69d 100644 --- a/drivers/mtd/maps/rbtx4939-flash.c +++ b/drivers/mtd/maps/rbtx4939-flash.c | |||
@@ -34,10 +34,9 @@ static int rbtx4939_flash_remove(struct platform_device *dev) | |||
34 | info = platform_get_drvdata(dev); | 34 | info = platform_get_drvdata(dev); |
35 | if (!info) | 35 | if (!info) |
36 | return 0; | 36 | return 0; |
37 | platform_set_drvdata(dev, NULL); | ||
38 | 37 | ||
39 | if (info->mtd) { | 38 | if (info->mtd) { |
40 | struct rbtx4939_flash_data *pdata = dev->dev.platform_data; | 39 | struct rbtx4939_flash_data *pdata = dev_get_platdata(&dev->dev); |
41 | 40 | ||
42 | mtd_device_unregister(info->mtd); | 41 | mtd_device_unregister(info->mtd); |
43 | map_destroy(info->mtd); | 42 | map_destroy(info->mtd); |
@@ -57,7 +56,7 @@ static int rbtx4939_flash_probe(struct platform_device *dev) | |||
57 | int err = 0; | 56 | int err = 0; |
58 | unsigned long size; | 57 | unsigned long size; |
59 | 58 | ||
60 | pdata = dev->dev.platform_data; | 59 | pdata = dev_get_platdata(&dev->dev); |
61 | if (!pdata) | 60 | if (!pdata) |
62 | return -ENODEV; | 61 | return -ENODEV; |
63 | 62 | ||
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c index 29e3dcaa1d90..8fc06bf111c4 100644 --- a/drivers/mtd/maps/sa1100-flash.c +++ b/drivers/mtd/maps/sa1100-flash.c | |||
@@ -248,7 +248,7 @@ static const char * const part_probes[] = { "cmdlinepart", "RedBoot", NULL }; | |||
248 | 248 | ||
249 | static int sa1100_mtd_probe(struct platform_device *pdev) | 249 | static int sa1100_mtd_probe(struct platform_device *pdev) |
250 | { | 250 | { |
251 | struct flash_platform_data *plat = pdev->dev.platform_data; | 251 | struct flash_platform_data *plat = dev_get_platdata(&pdev->dev); |
252 | struct sa_info *info; | 252 | struct sa_info *info; |
253 | int err; | 253 | int err; |
254 | 254 | ||
@@ -277,9 +277,8 @@ static int sa1100_mtd_probe(struct platform_device *pdev) | |||
277 | static int __exit sa1100_mtd_remove(struct platform_device *pdev) | 277 | static int __exit sa1100_mtd_remove(struct platform_device *pdev) |
278 | { | 278 | { |
279 | struct sa_info *info = platform_get_drvdata(pdev); | 279 | struct sa_info *info = platform_get_drvdata(pdev); |
280 | struct flash_platform_data *plat = pdev->dev.platform_data; | 280 | struct flash_platform_data *plat = dev_get_platdata(&pdev->dev); |
281 | 281 | ||
282 | platform_set_drvdata(pdev, NULL); | ||
283 | sa1100_destroy(info, plat); | 282 | sa1100_destroy(info, plat); |
284 | 283 | ||
285 | return 0; | 284 | return 0; |
diff --git a/drivers/mtd/maps/vmax301.c b/drivers/mtd/maps/vmax301.c deleted file mode 100644 index 5e68de73eabc..000000000000 --- a/drivers/mtd/maps/vmax301.c +++ /dev/null | |||
@@ -1,196 +0,0 @@ | |||
1 | /* ###################################################################### | ||
2 | |||
3 | Tempustech VMAX SBC301 MTD Driver. | ||
4 | |||
5 | The VMAx 301 is a SBC based on . It | ||
6 | comes with three builtin AMD 29F016B flash chips and a socket for SRAM or | ||
7 | more flash. Each unit has it's own 8k mapping into a settable region | ||
8 | (0xD8000). There are two 8k mappings for each MTD, the first is always set | ||
9 | to the lower 8k of the device the second is paged. Writing a 16 bit page | ||
10 | value to anywhere in the first 8k will cause the second 8k to page around. | ||
11 | |||
12 | To boot the device a bios extension must be installed into the first 8k | ||
13 | of flash that is smart enough to copy itself down, page in the rest of | ||
14 | itself and begin executing. | ||
15 | |||
16 | ##################################################################### */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/ioport.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/spinlock.h> | ||
22 | #include <asm/io.h> | ||
23 | |||
24 | #include <linux/mtd/map.h> | ||
25 | #include <linux/mtd/mtd.h> | ||
26 | |||
27 | |||
28 | #define WINDOW_START 0xd8000 | ||
29 | #define WINDOW_LENGTH 0x2000 | ||
30 | #define WINDOW_SHIFT 25 | ||
31 | #define WINDOW_MASK 0x1FFF | ||
32 | |||
33 | /* Actually we could use two spinlocks, but we'd have to have | ||
34 | more private space in the struct map_info. We lose a little | ||
35 | performance like this, but we'd probably lose more by having | ||
36 | the extra indirection from having one of the map->map_priv | ||
37 | fields pointing to yet another private struct. | ||
38 | */ | ||
39 | static DEFINE_SPINLOCK(vmax301_spin); | ||
40 | |||
41 | static void __vmax301_page(struct map_info *map, unsigned long page) | ||
42 | { | ||
43 | writew(page, map->map_priv_2 - WINDOW_LENGTH); | ||
44 | map->map_priv_1 = page; | ||
45 | } | ||
46 | |||
47 | static inline void vmax301_page(struct map_info *map, | ||
48 | unsigned long ofs) | ||
49 | { | ||
50 | unsigned long page = (ofs >> WINDOW_SHIFT); | ||
51 | if (map->map_priv_1 != page) | ||
52 | __vmax301_page(map, page); | ||
53 | } | ||
54 | |||
55 | static map_word vmax301_read8(struct map_info *map, unsigned long ofs) | ||
56 | { | ||
57 | map_word ret; | ||
58 | spin_lock(&vmax301_spin); | ||
59 | vmax301_page(map, ofs); | ||
60 | ret.x[0] = readb(map->map_priv_2 + (ofs & WINDOW_MASK)); | ||
61 | spin_unlock(&vmax301_spin); | ||
62 | return ret; | ||
63 | } | ||
64 | |||
65 | static void vmax301_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) | ||
66 | { | ||
67 | while(len) { | ||
68 | unsigned long thislen = len; | ||
69 | if (len > (WINDOW_LENGTH - (from & WINDOW_MASK))) | ||
70 | thislen = WINDOW_LENGTH-(from & WINDOW_MASK); | ||
71 | spin_lock(&vmax301_spin); | ||
72 | vmax301_page(map, from); | ||
73 | memcpy_fromio(to, map->map_priv_2 + from, thislen); | ||
74 | spin_unlock(&vmax301_spin); | ||
75 | to += thislen; | ||
76 | from += thislen; | ||
77 | len -= thislen; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | static void vmax301_write8(struct map_info *map, map_word d, unsigned long adr) | ||
82 | { | ||
83 | spin_lock(&vmax301_spin); | ||
84 | vmax301_page(map, adr); | ||
85 | writeb(d.x[0], map->map_priv_2 + (adr & WINDOW_MASK)); | ||
86 | spin_unlock(&vmax301_spin); | ||
87 | } | ||
88 | |||
89 | static void vmax301_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) | ||
90 | { | ||
91 | while(len) { | ||
92 | unsigned long thislen = len; | ||
93 | if (len > (WINDOW_LENGTH - (to & WINDOW_MASK))) | ||
94 | thislen = WINDOW_LENGTH-(to & WINDOW_MASK); | ||
95 | |||
96 | spin_lock(&vmax301_spin); | ||
97 | vmax301_page(map, to); | ||
98 | memcpy_toio(map->map_priv_2 + to, from, thislen); | ||
99 | spin_unlock(&vmax301_spin); | ||
100 | to += thislen; | ||
101 | from += thislen; | ||
102 | len -= thislen; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | static struct map_info vmax_map[2] = { | ||
107 | { | ||
108 | .name = "VMAX301 Internal Flash", | ||
109 | .phys = NO_XIP, | ||
110 | .size = 3*2*1024*1024, | ||
111 | .bankwidth = 1, | ||
112 | .read = vmax301_read8, | ||
113 | .copy_from = vmax301_copy_from, | ||
114 | .write = vmax301_write8, | ||
115 | .copy_to = vmax301_copy_to, | ||
116 | .map_priv_1 = WINDOW_START + WINDOW_LENGTH, | ||
117 | .map_priv_2 = 0xFFFFFFFF | ||
118 | }, | ||
119 | { | ||
120 | .name = "VMAX301 Socket", | ||
121 | .phys = NO_XIP, | ||
122 | .size = 0, | ||
123 | .bankwidth = 1, | ||
124 | .read = vmax301_read8, | ||
125 | .copy_from = vmax301_copy_from, | ||
126 | .write = vmax301_write8, | ||
127 | .copy_to = vmax301_copy_to, | ||
128 | .map_priv_1 = WINDOW_START + (3*WINDOW_LENGTH), | ||
129 | .map_priv_2 = 0xFFFFFFFF | ||
130 | } | ||
131 | }; | ||
132 | |||
133 | static struct mtd_info *vmax_mtd[2] = {NULL, NULL}; | ||
134 | |||
135 | static void __exit cleanup_vmax301(void) | ||
136 | { | ||
137 | int i; | ||
138 | |||
139 | for (i=0; i<2; i++) { | ||
140 | if (vmax_mtd[i]) { | ||
141 | mtd_device_unregister(vmax_mtd[i]); | ||
142 | map_destroy(vmax_mtd[i]); | ||
143 | } | ||
144 | } | ||
145 | iounmap((void *)vmax_map[0].map_priv_1 - WINDOW_START); | ||
146 | } | ||
147 | |||
148 | static int __init init_vmax301(void) | ||
149 | { | ||
150 | int i; | ||
151 | unsigned long iomapadr; | ||
152 | // Print out our little header.. | ||
153 | printk("Tempustech VMAX 301 MEM:0x%x-0x%x\n",WINDOW_START, | ||
154 | WINDOW_START+4*WINDOW_LENGTH); | ||
155 | |||
156 | iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH*4); | ||
157 | if (!iomapadr) { | ||
158 | printk("Failed to ioremap memory region\n"); | ||
159 | return -EIO; | ||
160 | } | ||
161 | /* Put the address in the map's private data area. | ||
162 | We store the actual MTD IO address rather than the | ||
163 | address of the first half, because it's used more | ||
164 | often. | ||
165 | */ | ||
166 | vmax_map[0].map_priv_2 = iomapadr + WINDOW_START; | ||
167 | vmax_map[1].map_priv_2 = iomapadr + (3*WINDOW_START); | ||
168 | |||
169 | for (i=0; i<2; i++) { | ||
170 | vmax_mtd[i] = do_map_probe("cfi_probe", &vmax_map[i]); | ||
171 | if (!vmax_mtd[i]) | ||
172 | vmax_mtd[i] = do_map_probe("jedec", &vmax_map[i]); | ||
173 | if (!vmax_mtd[i]) | ||
174 | vmax_mtd[i] = do_map_probe("map_ram", &vmax_map[i]); | ||
175 | if (!vmax_mtd[i]) | ||
176 | vmax_mtd[i] = do_map_probe("map_rom", &vmax_map[i]); | ||
177 | if (vmax_mtd[i]) { | ||
178 | vmax_mtd[i]->owner = THIS_MODULE; | ||
179 | mtd_device_register(vmax_mtd[i], NULL, 0); | ||
180 | } | ||
181 | } | ||
182 | |||
183 | if (!vmax_mtd[0] && !vmax_mtd[1]) { | ||
184 | iounmap((void *)iomapadr); | ||
185 | return -ENXIO; | ||
186 | } | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | module_init(init_vmax301); | ||
192 | module_exit(cleanup_vmax301); | ||
193 | |||
194 | MODULE_LICENSE("GPL"); | ||
195 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); | ||
196 | MODULE_DESCRIPTION("MTD map driver for Tempustech VMAX SBC301 board"); | ||
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 048c823f5c51..5e14d540ba2f 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c | |||
@@ -285,6 +285,16 @@ static DEVICE_ATTR(bitflip_threshold, S_IRUGO | S_IWUSR, | |||
285 | mtd_bitflip_threshold_show, | 285 | mtd_bitflip_threshold_show, |
286 | mtd_bitflip_threshold_store); | 286 | mtd_bitflip_threshold_store); |
287 | 287 | ||
288 | static ssize_t mtd_ecc_step_size_show(struct device *dev, | ||
289 | struct device_attribute *attr, char *buf) | ||
290 | { | ||
291 | struct mtd_info *mtd = dev_get_drvdata(dev); | ||
292 | |||
293 | return snprintf(buf, PAGE_SIZE, "%u\n", mtd->ecc_step_size); | ||
294 | |||
295 | } | ||
296 | static DEVICE_ATTR(ecc_step_size, S_IRUGO, mtd_ecc_step_size_show, NULL); | ||
297 | |||
288 | static struct attribute *mtd_attrs[] = { | 298 | static struct attribute *mtd_attrs[] = { |
289 | &dev_attr_type.attr, | 299 | &dev_attr_type.attr, |
290 | &dev_attr_flags.attr, | 300 | &dev_attr_flags.attr, |
@@ -296,6 +306,7 @@ static struct attribute *mtd_attrs[] = { | |||
296 | &dev_attr_numeraseregions.attr, | 306 | &dev_attr_numeraseregions.attr, |
297 | &dev_attr_name.attr, | 307 | &dev_attr_name.attr, |
298 | &dev_attr_ecc_strength.attr, | 308 | &dev_attr_ecc_strength.attr, |
309 | &dev_attr_ecc_step_size.attr, | ||
299 | &dev_attr_bitflip_threshold.attr, | 310 | &dev_attr_bitflip_threshold.attr, |
300 | NULL, | 311 | NULL, |
301 | }; | 312 | }; |
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 301493382cd0..6e732c3820c1 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c | |||
@@ -516,6 +516,7 @@ static struct mtd_part *allocate_partition(struct mtd_info *master, | |||
516 | } | 516 | } |
517 | 517 | ||
518 | slave->mtd.ecclayout = master->ecclayout; | 518 | slave->mtd.ecclayout = master->ecclayout; |
519 | slave->mtd.ecc_step_size = master->ecc_step_size; | ||
519 | slave->mtd.ecc_strength = master->ecc_strength; | 520 | slave->mtd.ecc_strength = master->ecc_strength; |
520 | slave->mtd.bitflip_threshold = master->bitflip_threshold; | 521 | slave->mtd.bitflip_threshold = master->bitflip_threshold; |
521 | 522 | ||
diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c index c92f0f6bc130..8b33b26eb12b 100644 --- a/drivers/mtd/mtdswap.c +++ b/drivers/mtd/mtdswap.c | |||
@@ -1425,7 +1425,7 @@ static void mtdswap_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) | |||
1425 | return; | 1425 | return; |
1426 | 1426 | ||
1427 | while ((this_opt = strsep(&parts, ",")) != NULL) { | 1427 | while ((this_opt = strsep(&parts, ",")) != NULL) { |
1428 | if (strict_strtoul(this_opt, 0, &part) < 0) | 1428 | if (kstrtoul(this_opt, 0, &part) < 0) |
1429 | return; | 1429 | return; |
1430 | 1430 | ||
1431 | if (mtd->index == part) | 1431 | if (mtd->index == part) |
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 50543f166215..d88529841d3f 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -43,6 +43,7 @@ config MTD_SM_COMMON | |||
43 | 43 | ||
44 | config MTD_NAND_DENALI | 44 | config MTD_NAND_DENALI |
45 | tristate "Support Denali NAND controller" | 45 | tristate "Support Denali NAND controller" |
46 | depends on HAS_DMA | ||
46 | help | 47 | help |
47 | Enable support for the Denali NAND controller. This should be | 48 | Enable support for the Denali NAND controller. This should be |
48 | combined with either the PCI or platform drivers to provide device | 49 | combined with either the PCI or platform drivers to provide device |
@@ -75,7 +76,7 @@ config MTD_NAND_DENALI_SCRATCH_REG_ADDR | |||
75 | 76 | ||
76 | config MTD_NAND_GPIO | 77 | config MTD_NAND_GPIO |
77 | tristate "GPIO NAND Flash driver" | 78 | tristate "GPIO NAND Flash driver" |
78 | depends on GPIOLIB && ARM | 79 | depends on GPIOLIB |
79 | help | 80 | help |
80 | This enables a GPIO based NAND flash driver. | 81 | This enables a GPIO based NAND flash driver. |
81 | 82 | ||
@@ -354,7 +355,7 @@ config MTD_NAND_ATMEL | |||
354 | 355 | ||
355 | config MTD_NAND_PXA3xx | 356 | config MTD_NAND_PXA3xx |
356 | tristate "Support for NAND flash devices on PXA3xx" | 357 | tristate "Support for NAND flash devices on PXA3xx" |
357 | depends on PXA3xx || ARCH_MMP | 358 | depends on PXA3xx || ARCH_MMP || PLAT_ORION |
358 | help | 359 | help |
359 | This enables the driver for the NAND flash device found on | 360 | This enables the driver for the NAND flash device found on |
360 | PXA3xx processors | 361 | PXA3xx processors |
@@ -432,13 +433,6 @@ config MTD_NAND_PLATFORM | |||
432 | devices. You will need to provide platform-specific functions | 433 | devices. You will need to provide platform-specific functions |
433 | via platform_data. | 434 | via platform_data. |
434 | 435 | ||
435 | config MTD_ALAUDA | ||
436 | tristate "MTD driver for Olympus MAUSB-10 and Fujifilm DPC-R1" | ||
437 | depends on USB | ||
438 | help | ||
439 | These two (and possibly other) Alauda-based cardreaders for | ||
440 | SmartMedia and xD allow raw flash access. | ||
441 | |||
442 | config MTD_NAND_ORION | 436 | config MTD_NAND_ORION |
443 | tristate "NAND Flash support for Marvell Orion SoC" | 437 | tristate "NAND Flash support for Marvell Orion SoC" |
444 | depends on PLAT_ORION | 438 | depends on PLAT_ORION |
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index bb8189172f62..542b5689eb63 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile | |||
@@ -31,7 +31,6 @@ obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o | |||
31 | obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o | 31 | obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o |
32 | obj-$(CONFIG_MTD_NAND_TMIO) += tmio_nand.o | 32 | obj-$(CONFIG_MTD_NAND_TMIO) += tmio_nand.o |
33 | obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o | 33 | obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o |
34 | obj-$(CONFIG_MTD_ALAUDA) += alauda.o | ||
35 | obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o | 34 | obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o |
36 | obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o | 35 | obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o |
37 | obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o | 36 | obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o |
diff --git a/drivers/mtd/nand/alauda.c b/drivers/mtd/nand/alauda.c deleted file mode 100644 index 60a0dfdb0808..000000000000 --- a/drivers/mtd/nand/alauda.c +++ /dev/null | |||
@@ -1,723 +0,0 @@ | |||
1 | /* | ||
2 | * MTD driver for Alauda chips | ||
3 | * | ||
4 | * Copyright (C) 2007 Joern Engel <joern@logfs.org> | ||
5 | * | ||
6 | * Based on drivers/usb/usb-skeleton.c which is: | ||
7 | * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) | ||
8 | * and on drivers/usb/storage/alauda.c, which is: | ||
9 | * (c) 2005 Daniel Drake <dsd@gentoo.org> | ||
10 | * | ||
11 | * Idea and initial work by Arnd Bergmann <arnd@arndb.de> | ||
12 | */ | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/kref.h> | ||
19 | #include <linux/usb.h> | ||
20 | #include <linux/mutex.h> | ||
21 | #include <linux/mtd/mtd.h> | ||
22 | #include <linux/mtd/nand_ecc.h> | ||
23 | |||
24 | /* Control commands */ | ||
25 | #define ALAUDA_GET_XD_MEDIA_STATUS 0x08 | ||
26 | #define ALAUDA_ACK_XD_MEDIA_CHANGE 0x0a | ||
27 | #define ALAUDA_GET_XD_MEDIA_SIG 0x86 | ||
28 | |||
29 | /* Common prefix */ | ||
30 | #define ALAUDA_BULK_CMD 0x40 | ||
31 | |||
32 | /* The two ports */ | ||
33 | #define ALAUDA_PORT_XD 0x00 | ||
34 | #define ALAUDA_PORT_SM 0x01 | ||
35 | |||
36 | /* Bulk commands */ | ||
37 | #define ALAUDA_BULK_READ_PAGE 0x84 | ||
38 | #define ALAUDA_BULK_READ_OOB 0x85 /* don't use, there's a chip bug */ | ||
39 | #define ALAUDA_BULK_READ_BLOCK 0x94 | ||
40 | #define ALAUDA_BULK_ERASE_BLOCK 0xa3 | ||
41 | #define ALAUDA_BULK_WRITE_PAGE 0xa4 | ||
42 | #define ALAUDA_BULK_WRITE_BLOCK 0xb4 | ||
43 | #define ALAUDA_BULK_RESET_MEDIA 0xe0 | ||
44 | |||
45 | /* Address shifting */ | ||
46 | #define PBA_LO(pba) ((pba & 0xF) << 5) | ||
47 | #define PBA_HI(pba) (pba >> 3) | ||
48 | #define PBA_ZONE(pba) (pba >> 11) | ||
49 | |||
50 | #define TIMEOUT HZ | ||
51 | |||
52 | static const struct usb_device_id alauda_table[] = { | ||
53 | { USB_DEVICE(0x0584, 0x0008) }, /* Fujifilm DPC-R1 */ | ||
54 | { USB_DEVICE(0x07b4, 0x010a) }, /* Olympus MAUSB-10 */ | ||
55 | { } | ||
56 | }; | ||
57 | MODULE_DEVICE_TABLE(usb, alauda_table); | ||
58 | |||
59 | struct alauda_card { | ||
60 | u8 id; /* id byte */ | ||
61 | u8 chipshift; /* 1<<chipshift total size */ | ||
62 | u8 pageshift; /* 1<<pageshift page size */ | ||
63 | u8 blockshift; /* 1<<blockshift block size */ | ||
64 | }; | ||
65 | |||
66 | struct alauda { | ||
67 | struct usb_device *dev; | ||
68 | struct usb_interface *interface; | ||
69 | struct mtd_info *mtd; | ||
70 | struct alauda_card *card; | ||
71 | struct mutex card_mutex; | ||
72 | u32 pagemask; | ||
73 | u32 bytemask; | ||
74 | u32 blockmask; | ||
75 | unsigned int write_out; | ||
76 | unsigned int bulk_in; | ||
77 | unsigned int bulk_out; | ||
78 | u8 port; | ||
79 | struct kref kref; | ||
80 | }; | ||
81 | |||
82 | static struct alauda_card alauda_card_ids[] = { | ||
83 | /* NAND flash */ | ||
84 | { 0x6e, 20, 8, 12}, /* 1 MB */ | ||
85 | { 0xe8, 20, 8, 12}, /* 1 MB */ | ||
86 | { 0xec, 20, 8, 12}, /* 1 MB */ | ||
87 | { 0x64, 21, 8, 12}, /* 2 MB */ | ||
88 | { 0xea, 21, 8, 12}, /* 2 MB */ | ||
89 | { 0x6b, 22, 9, 13}, /* 4 MB */ | ||
90 | { 0xe3, 22, 9, 13}, /* 4 MB */ | ||
91 | { 0xe5, 22, 9, 13}, /* 4 MB */ | ||
92 | { 0xe6, 23, 9, 13}, /* 8 MB */ | ||
93 | { 0x73, 24, 9, 14}, /* 16 MB */ | ||
94 | { 0x75, 25, 9, 14}, /* 32 MB */ | ||
95 | { 0x76, 26, 9, 14}, /* 64 MB */ | ||
96 | { 0x79, 27, 9, 14}, /* 128 MB */ | ||
97 | { 0x71, 28, 9, 14}, /* 256 MB */ | ||
98 | |||
99 | /* MASK ROM */ | ||
100 | { 0x5d, 21, 9, 13}, /* 2 MB */ | ||
101 | { 0xd5, 22, 9, 13}, /* 4 MB */ | ||
102 | { 0xd6, 23, 9, 13}, /* 8 MB */ | ||
103 | { 0x57, 24, 9, 13}, /* 16 MB */ | ||
104 | { 0x58, 25, 9, 13}, /* 32 MB */ | ||
105 | { } | ||
106 | }; | ||
107 | |||
108 | static struct alauda_card *get_card(u8 id) | ||
109 | { | ||
110 | struct alauda_card *card; | ||
111 | |||
112 | for (card = alauda_card_ids; card->id; card++) | ||
113 | if (card->id == id) | ||
114 | return card; | ||
115 | return NULL; | ||
116 | } | ||
117 | |||
118 | static void alauda_delete(struct kref *kref) | ||
119 | { | ||
120 | struct alauda *al = container_of(kref, struct alauda, kref); | ||
121 | |||
122 | if (al->mtd) { | ||
123 | mtd_device_unregister(al->mtd); | ||
124 | kfree(al->mtd); | ||
125 | } | ||
126 | usb_put_dev(al->dev); | ||
127 | kfree(al); | ||
128 | } | ||
129 | |||
130 | static int alauda_get_media_status(struct alauda *al, void *buf) | ||
131 | { | ||
132 | int ret; | ||
133 | |||
134 | mutex_lock(&al->card_mutex); | ||
135 | ret = usb_control_msg(al->dev, usb_rcvctrlpipe(al->dev, 0), | ||
136 | ALAUDA_GET_XD_MEDIA_STATUS, 0xc0, 0, 1, buf, 2, HZ); | ||
137 | mutex_unlock(&al->card_mutex); | ||
138 | return ret; | ||
139 | } | ||
140 | |||
141 | static int alauda_ack_media(struct alauda *al) | ||
142 | { | ||
143 | int ret; | ||
144 | |||
145 | mutex_lock(&al->card_mutex); | ||
146 | ret = usb_control_msg(al->dev, usb_sndctrlpipe(al->dev, 0), | ||
147 | ALAUDA_ACK_XD_MEDIA_CHANGE, 0x40, 0, 1, NULL, 0, HZ); | ||
148 | mutex_unlock(&al->card_mutex); | ||
149 | return ret; | ||
150 | } | ||
151 | |||
152 | static int alauda_get_media_signatures(struct alauda *al, void *buf) | ||
153 | { | ||
154 | int ret; | ||
155 | |||
156 | mutex_lock(&al->card_mutex); | ||
157 | ret = usb_control_msg(al->dev, usb_rcvctrlpipe(al->dev, 0), | ||
158 | ALAUDA_GET_XD_MEDIA_SIG, 0xc0, 0, 0, buf, 4, HZ); | ||
159 | mutex_unlock(&al->card_mutex); | ||
160 | return ret; | ||
161 | } | ||
162 | |||
163 | static void alauda_reset(struct alauda *al) | ||
164 | { | ||
165 | u8 command[] = { | ||
166 | ALAUDA_BULK_CMD, ALAUDA_BULK_RESET_MEDIA, 0, 0, | ||
167 | 0, 0, 0, 0, al->port | ||
168 | }; | ||
169 | mutex_lock(&al->card_mutex); | ||
170 | usb_bulk_msg(al->dev, al->bulk_out, command, 9, NULL, HZ); | ||
171 | mutex_unlock(&al->card_mutex); | ||
172 | } | ||
173 | |||
174 | static void correct_data(void *buf, void *read_ecc, | ||
175 | int *corrected, int *uncorrected) | ||
176 | { | ||
177 | u8 calc_ecc[3]; | ||
178 | int err; | ||
179 | |||
180 | nand_calculate_ecc(NULL, buf, calc_ecc); | ||
181 | err = nand_correct_data(NULL, buf, read_ecc, calc_ecc); | ||
182 | if (err) { | ||
183 | if (err > 0) | ||
184 | (*corrected)++; | ||
185 | else | ||
186 | (*uncorrected)++; | ||
187 | } | ||
188 | } | ||
189 | |||
190 | struct alauda_sg_request { | ||
191 | struct urb *urb[3]; | ||
192 | struct completion comp; | ||
193 | }; | ||
194 | |||
195 | static void alauda_complete(struct urb *urb) | ||
196 | { | ||
197 | struct completion *comp = urb->context; | ||
198 | |||
199 | if (comp) | ||
200 | complete(comp); | ||
201 | } | ||
202 | |||
203 | static int __alauda_read_page(struct mtd_info *mtd, loff_t from, void *buf, | ||
204 | void *oob) | ||
205 | { | ||
206 | struct alauda_sg_request sg; | ||
207 | struct alauda *al = mtd->priv; | ||
208 | u32 pba = from >> al->card->blockshift; | ||
209 | u32 page = (from >> al->card->pageshift) & al->pagemask; | ||
210 | u8 command[] = { | ||
211 | ALAUDA_BULK_CMD, ALAUDA_BULK_READ_PAGE, PBA_HI(pba), | ||
212 | PBA_ZONE(pba), 0, PBA_LO(pba) + page, 1, 0, al->port | ||
213 | }; | ||
214 | int i, err; | ||
215 | |||
216 | for (i=0; i<3; i++) | ||
217 | sg.urb[i] = NULL; | ||
218 | |||
219 | err = -ENOMEM; | ||
220 | for (i=0; i<3; i++) { | ||
221 | sg.urb[i] = usb_alloc_urb(0, GFP_NOIO); | ||
222 | if (!sg.urb[i]) | ||
223 | goto out; | ||
224 | } | ||
225 | init_completion(&sg.comp); | ||
226 | usb_fill_bulk_urb(sg.urb[0], al->dev, al->bulk_out, command, 9, | ||
227 | alauda_complete, NULL); | ||
228 | usb_fill_bulk_urb(sg.urb[1], al->dev, al->bulk_in, buf, mtd->writesize, | ||
229 | alauda_complete, NULL); | ||
230 | usb_fill_bulk_urb(sg.urb[2], al->dev, al->bulk_in, oob, 16, | ||
231 | alauda_complete, &sg.comp); | ||
232 | |||
233 | mutex_lock(&al->card_mutex); | ||
234 | for (i=0; i<3; i++) { | ||
235 | err = usb_submit_urb(sg.urb[i], GFP_NOIO); | ||
236 | if (err) | ||
237 | goto cancel; | ||
238 | } | ||
239 | if (!wait_for_completion_timeout(&sg.comp, TIMEOUT)) { | ||
240 | err = -ETIMEDOUT; | ||
241 | cancel: | ||
242 | for (i=0; i<3; i++) { | ||
243 | usb_kill_urb(sg.urb[i]); | ||
244 | } | ||
245 | } | ||
246 | mutex_unlock(&al->card_mutex); | ||
247 | |||
248 | out: | ||
249 | usb_free_urb(sg.urb[0]); | ||
250 | usb_free_urb(sg.urb[1]); | ||
251 | usb_free_urb(sg.urb[2]); | ||
252 | return err; | ||
253 | } | ||
254 | |||
255 | static int alauda_read_page(struct mtd_info *mtd, loff_t from, | ||
256 | void *buf, u8 *oob, int *corrected, int *uncorrected) | ||
257 | { | ||
258 | int err; | ||
259 | |||
260 | err = __alauda_read_page(mtd, from, buf, oob); | ||
261 | if (err) | ||
262 | return err; | ||
263 | correct_data(buf, oob+13, corrected, uncorrected); | ||
264 | correct_data(buf+256, oob+8, corrected, uncorrected); | ||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | static int alauda_write_page(struct mtd_info *mtd, loff_t to, void *buf, | ||
269 | void *oob) | ||
270 | { | ||
271 | struct alauda_sg_request sg; | ||
272 | struct alauda *al = mtd->priv; | ||
273 | u32 pba = to >> al->card->blockshift; | ||
274 | u32 page = (to >> al->card->pageshift) & al->pagemask; | ||
275 | u8 command[] = { | ||
276 | ALAUDA_BULK_CMD, ALAUDA_BULK_WRITE_PAGE, PBA_HI(pba), | ||
277 | PBA_ZONE(pba), 0, PBA_LO(pba) + page, 32, 0, al->port | ||
278 | }; | ||
279 | int i, err; | ||
280 | |||
281 | for (i=0; i<3; i++) | ||
282 | sg.urb[i] = NULL; | ||
283 | |||
284 | err = -ENOMEM; | ||
285 | for (i=0; i<3; i++) { | ||
286 | sg.urb[i] = usb_alloc_urb(0, GFP_NOIO); | ||
287 | if (!sg.urb[i]) | ||
288 | goto out; | ||
289 | } | ||
290 | init_completion(&sg.comp); | ||
291 | usb_fill_bulk_urb(sg.urb[0], al->dev, al->bulk_out, command, 9, | ||
292 | alauda_complete, NULL); | ||
293 | usb_fill_bulk_urb(sg.urb[1], al->dev, al->write_out, buf,mtd->writesize, | ||
294 | alauda_complete, NULL); | ||
295 | usb_fill_bulk_urb(sg.urb[2], al->dev, al->write_out, oob, 16, | ||
296 | alauda_complete, &sg.comp); | ||
297 | |||
298 | mutex_lock(&al->card_mutex); | ||
299 | for (i=0; i<3; i++) { | ||
300 | err = usb_submit_urb(sg.urb[i], GFP_NOIO); | ||
301 | if (err) | ||
302 | goto cancel; | ||
303 | } | ||
304 | if (!wait_for_completion_timeout(&sg.comp, TIMEOUT)) { | ||
305 | err = -ETIMEDOUT; | ||
306 | cancel: | ||
307 | for (i=0; i<3; i++) { | ||
308 | usb_kill_urb(sg.urb[i]); | ||
309 | } | ||
310 | } | ||
311 | mutex_unlock(&al->card_mutex); | ||
312 | |||
313 | out: | ||
314 | usb_free_urb(sg.urb[0]); | ||
315 | usb_free_urb(sg.urb[1]); | ||
316 | usb_free_urb(sg.urb[2]); | ||
317 | return err; | ||
318 | } | ||
319 | |||
320 | static int alauda_erase_block(struct mtd_info *mtd, loff_t ofs) | ||
321 | { | ||
322 | struct alauda_sg_request sg; | ||
323 | struct alauda *al = mtd->priv; | ||
324 | u32 pba = ofs >> al->card->blockshift; | ||
325 | u8 command[] = { | ||
326 | ALAUDA_BULK_CMD, ALAUDA_BULK_ERASE_BLOCK, PBA_HI(pba), | ||
327 | PBA_ZONE(pba), 0, PBA_LO(pba), 0x02, 0, al->port | ||
328 | }; | ||
329 | u8 buf[2]; | ||
330 | int i, err; | ||
331 | |||
332 | for (i=0; i<2; i++) | ||
333 | sg.urb[i] = NULL; | ||
334 | |||
335 | err = -ENOMEM; | ||
336 | for (i=0; i<2; i++) { | ||
337 | sg.urb[i] = usb_alloc_urb(0, GFP_NOIO); | ||
338 | if (!sg.urb[i]) | ||
339 | goto out; | ||
340 | } | ||
341 | init_completion(&sg.comp); | ||
342 | usb_fill_bulk_urb(sg.urb[0], al->dev, al->bulk_out, command, 9, | ||
343 | alauda_complete, NULL); | ||
344 | usb_fill_bulk_urb(sg.urb[1], al->dev, al->bulk_in, buf, 2, | ||
345 | alauda_complete, &sg.comp); | ||
346 | |||
347 | mutex_lock(&al->card_mutex); | ||
348 | for (i=0; i<2; i++) { | ||
349 | err = usb_submit_urb(sg.urb[i], GFP_NOIO); | ||
350 | if (err) | ||
351 | goto cancel; | ||
352 | } | ||
353 | if (!wait_for_completion_timeout(&sg.comp, TIMEOUT)) { | ||
354 | err = -ETIMEDOUT; | ||
355 | cancel: | ||
356 | for (i=0; i<2; i++) { | ||
357 | usb_kill_urb(sg.urb[i]); | ||
358 | } | ||
359 | } | ||
360 | mutex_unlock(&al->card_mutex); | ||
361 | |||
362 | out: | ||
363 | usb_free_urb(sg.urb[0]); | ||
364 | usb_free_urb(sg.urb[1]); | ||
365 | return err; | ||
366 | } | ||
367 | |||
368 | static int alauda_read_oob(struct mtd_info *mtd, loff_t from, void *oob) | ||
369 | { | ||
370 | static u8 ignore_buf[512]; /* write only */ | ||
371 | |||
372 | return __alauda_read_page(mtd, from, ignore_buf, oob); | ||
373 | } | ||
374 | |||
375 | static int alauda_isbad(struct mtd_info *mtd, loff_t ofs) | ||
376 | { | ||
377 | u8 oob[16]; | ||
378 | int err; | ||
379 | |||
380 | err = alauda_read_oob(mtd, ofs, oob); | ||
381 | if (err) | ||
382 | return err; | ||
383 | |||
384 | /* A block is marked bad if two or more bits are zero */ | ||
385 | return hweight8(oob[5]) >= 7 ? 0 : 1; | ||
386 | } | ||
387 | |||
388 | static int alauda_bounce_read(struct mtd_info *mtd, loff_t from, size_t len, | ||
389 | size_t *retlen, u_char *buf) | ||
390 | { | ||
391 | struct alauda *al = mtd->priv; | ||
392 | void *bounce_buf; | ||
393 | int err, corrected=0, uncorrected=0; | ||
394 | |||
395 | bounce_buf = kmalloc(mtd->writesize, GFP_KERNEL); | ||
396 | if (!bounce_buf) | ||
397 | return -ENOMEM; | ||
398 | |||
399 | *retlen = len; | ||
400 | while (len) { | ||
401 | u8 oob[16]; | ||
402 | size_t byte = from & al->bytemask; | ||
403 | size_t cplen = min(len, mtd->writesize - byte); | ||
404 | |||
405 | err = alauda_read_page(mtd, from, bounce_buf, oob, | ||
406 | &corrected, &uncorrected); | ||
407 | if (err) | ||
408 | goto out; | ||
409 | |||
410 | memcpy(buf, bounce_buf + byte, cplen); | ||
411 | buf += cplen; | ||
412 | from += cplen; | ||
413 | len -= cplen; | ||
414 | } | ||
415 | err = 0; | ||
416 | if (corrected) | ||
417 | err = 1; /* return max_bitflips per ecc step */ | ||
418 | if (uncorrected) | ||
419 | err = -EBADMSG; | ||
420 | out: | ||
421 | kfree(bounce_buf); | ||
422 | return err; | ||
423 | } | ||
424 | |||
425 | static int alauda_read(struct mtd_info *mtd, loff_t from, size_t len, | ||
426 | size_t *retlen, u_char *buf) | ||
427 | { | ||
428 | struct alauda *al = mtd->priv; | ||
429 | int err, corrected=0, uncorrected=0; | ||
430 | |||
431 | if ((from & al->bytemask) || (len & al->bytemask)) | ||
432 | return alauda_bounce_read(mtd, from, len, retlen, buf); | ||
433 | |||
434 | *retlen = len; | ||
435 | while (len) { | ||
436 | u8 oob[16]; | ||
437 | |||
438 | err = alauda_read_page(mtd, from, buf, oob, | ||
439 | &corrected, &uncorrected); | ||
440 | if (err) | ||
441 | return err; | ||
442 | |||
443 | buf += mtd->writesize; | ||
444 | from += mtd->writesize; | ||
445 | len -= mtd->writesize; | ||
446 | } | ||
447 | err = 0; | ||
448 | if (corrected) | ||
449 | err = 1; /* return max_bitflips per ecc step */ | ||
450 | if (uncorrected) | ||
451 | err = -EBADMSG; | ||
452 | return err; | ||
453 | } | ||
454 | |||
455 | static int alauda_write(struct mtd_info *mtd, loff_t to, size_t len, | ||
456 | size_t *retlen, const u_char *buf) | ||
457 | { | ||
458 | struct alauda *al = mtd->priv; | ||
459 | int err; | ||
460 | |||
461 | if ((to & al->bytemask) || (len & al->bytemask)) | ||
462 | return -EINVAL; | ||
463 | |||
464 | *retlen = len; | ||
465 | while (len) { | ||
466 | u32 page = (to >> al->card->pageshift) & al->pagemask; | ||
467 | u8 oob[16] = { 'h', 'e', 'l', 'l', 'o', 0xff, 0xff, 0xff, | ||
468 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||
469 | |||
470 | /* don't write to bad blocks */ | ||
471 | if (page == 0) { | ||
472 | err = alauda_isbad(mtd, to); | ||
473 | if (err) { | ||
474 | return -EIO; | ||
475 | } | ||
476 | } | ||
477 | nand_calculate_ecc(mtd, buf, &oob[13]); | ||
478 | nand_calculate_ecc(mtd, buf+256, &oob[8]); | ||
479 | |||
480 | err = alauda_write_page(mtd, to, (void*)buf, oob); | ||
481 | if (err) | ||
482 | return err; | ||
483 | |||
484 | buf += mtd->writesize; | ||
485 | to += mtd->writesize; | ||
486 | len -= mtd->writesize; | ||
487 | } | ||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | static int __alauda_erase(struct mtd_info *mtd, struct erase_info *instr) | ||
492 | { | ||
493 | struct alauda *al = mtd->priv; | ||
494 | u32 ofs = instr->addr; | ||
495 | u32 len = instr->len; | ||
496 | int err; | ||
497 | |||
498 | if ((ofs & al->blockmask) || (len & al->blockmask)) | ||
499 | return -EINVAL; | ||
500 | |||
501 | while (len) { | ||
502 | /* don't erase bad blocks */ | ||
503 | err = alauda_isbad(mtd, ofs); | ||
504 | if (err > 0) | ||
505 | err = -EIO; | ||
506 | if (err < 0) | ||
507 | return err; | ||
508 | |||
509 | err = alauda_erase_block(mtd, ofs); | ||
510 | if (err < 0) | ||
511 | return err; | ||
512 | |||
513 | ofs += mtd->erasesize; | ||
514 | len -= mtd->erasesize; | ||
515 | } | ||
516 | return 0; | ||
517 | } | ||
518 | |||
519 | static int alauda_erase(struct mtd_info *mtd, struct erase_info *instr) | ||
520 | { | ||
521 | int err; | ||
522 | |||
523 | err = __alauda_erase(mtd, instr); | ||
524 | instr->state = err ? MTD_ERASE_FAILED : MTD_ERASE_DONE; | ||
525 | mtd_erase_callback(instr); | ||
526 | return err; | ||
527 | } | ||
528 | |||
529 | static int alauda_init_media(struct alauda *al) | ||
530 | { | ||
531 | u8 buf[4], *b0=buf, *b1=buf+1; | ||
532 | struct alauda_card *card; | ||
533 | struct mtd_info *mtd; | ||
534 | int err; | ||
535 | |||
536 | mtd = kzalloc(sizeof(*mtd), GFP_KERNEL); | ||
537 | if (!mtd) | ||
538 | return -ENOMEM; | ||
539 | |||
540 | for (;;) { | ||
541 | err = alauda_get_media_status(al, buf); | ||
542 | if (err < 0) | ||
543 | goto error; | ||
544 | if (*b0 & 0x10) | ||
545 | break; | ||
546 | msleep(20); | ||
547 | } | ||
548 | |||
549 | err = alauda_ack_media(al); | ||
550 | if (err) | ||
551 | goto error; | ||
552 | |||
553 | msleep(10); | ||
554 | |||
555 | err = alauda_get_media_status(al, buf); | ||
556 | if (err < 0) | ||
557 | goto error; | ||
558 | |||
559 | if (*b0 != 0x14) { | ||
560 | /* media not ready */ | ||
561 | err = -EIO; | ||
562 | goto error; | ||
563 | } | ||
564 | err = alauda_get_media_signatures(al, buf); | ||
565 | if (err < 0) | ||
566 | goto error; | ||
567 | |||
568 | card = get_card(*b1); | ||
569 | if (!card) { | ||
570 | printk(KERN_ERR"Alauda: unknown card id %02x\n", *b1); | ||
571 | err = -EIO; | ||
572 | goto error; | ||
573 | } | ||
574 | printk(KERN_INFO"pagesize=%x\nerasesize=%x\nsize=%xMiB\n", | ||
575 | 1<<card->pageshift, 1<<card->blockshift, | ||
576 | 1<<(card->chipshift-20)); | ||
577 | al->card = card; | ||
578 | al->pagemask = (1 << (card->blockshift - card->pageshift)) - 1; | ||
579 | al->bytemask = (1 << card->pageshift) - 1; | ||
580 | al->blockmask = (1 << card->blockshift) - 1; | ||
581 | |||
582 | mtd->name = "alauda"; | ||
583 | mtd->size = 1<<card->chipshift; | ||
584 | mtd->erasesize = 1<<card->blockshift; | ||
585 | mtd->writesize = 1<<card->pageshift; | ||
586 | mtd->type = MTD_NANDFLASH; | ||
587 | mtd->flags = MTD_CAP_NANDFLASH; | ||
588 | mtd->_read = alauda_read; | ||
589 | mtd->_write = alauda_write; | ||
590 | mtd->_erase = alauda_erase; | ||
591 | mtd->_block_isbad = alauda_isbad; | ||
592 | mtd->priv = al; | ||
593 | mtd->owner = THIS_MODULE; | ||
594 | mtd->ecc_strength = 1; | ||
595 | |||
596 | err = mtd_device_register(mtd, NULL, 0); | ||
597 | if (err) { | ||
598 | err = -ENFILE; | ||
599 | goto error; | ||
600 | } | ||
601 | |||
602 | al->mtd = mtd; | ||
603 | alauda_reset(al); /* no clue whether this is necessary */ | ||
604 | return 0; | ||
605 | error: | ||
606 | kfree(mtd); | ||
607 | return err; | ||
608 | } | ||
609 | |||
610 | static int alauda_check_media(struct alauda *al) | ||
611 | { | ||
612 | u8 buf[2], *b0 = buf, *b1 = buf+1; | ||
613 | int err; | ||
614 | |||
615 | err = alauda_get_media_status(al, buf); | ||
616 | if (err < 0) | ||
617 | return err; | ||
618 | |||
619 | if ((*b1 & 0x01) == 0) { | ||
620 | /* door open */ | ||
621 | return -EIO; | ||
622 | } | ||
623 | if ((*b0 & 0x80) || ((*b0 & 0x1F) == 0x10)) { | ||
624 | /* no media ? */ | ||
625 | return -EIO; | ||
626 | } | ||
627 | if (*b0 & 0x08) { | ||
628 | /* media change ? */ | ||
629 | return alauda_init_media(al); | ||
630 | } | ||
631 | return 0; | ||
632 | } | ||
633 | |||
634 | static int alauda_probe(struct usb_interface *interface, | ||
635 | const struct usb_device_id *id) | ||
636 | { | ||
637 | struct alauda *al; | ||
638 | struct usb_host_interface *iface; | ||
639 | struct usb_endpoint_descriptor *ep, | ||
640 | *ep_in=NULL, *ep_out=NULL, *ep_wr=NULL; | ||
641 | int i, err = -ENOMEM; | ||
642 | |||
643 | al = kzalloc(2*sizeof(*al), GFP_KERNEL); | ||
644 | if (!al) | ||
645 | goto error; | ||
646 | |||
647 | kref_init(&al->kref); | ||
648 | usb_set_intfdata(interface, al); | ||
649 | |||
650 | al->dev = usb_get_dev(interface_to_usbdev(interface)); | ||
651 | al->interface = interface; | ||
652 | |||
653 | iface = interface->cur_altsetting; | ||
654 | for (i = 0; i < iface->desc.bNumEndpoints; ++i) { | ||
655 | ep = &iface->endpoint[i].desc; | ||
656 | |||
657 | if (usb_endpoint_is_bulk_in(ep)) { | ||
658 | ep_in = ep; | ||
659 | } else if (usb_endpoint_is_bulk_out(ep)) { | ||
660 | if (i==0) | ||
661 | ep_wr = ep; | ||
662 | else | ||
663 | ep_out = ep; | ||
664 | } | ||
665 | } | ||
666 | err = -EIO; | ||
667 | if (!ep_wr || !ep_in || !ep_out) | ||
668 | goto error; | ||
669 | |||
670 | al->write_out = usb_sndbulkpipe(al->dev, | ||
671 | usb_endpoint_num(ep_wr)); | ||
672 | al->bulk_in = usb_rcvbulkpipe(al->dev, | ||
673 | usb_endpoint_num(ep_in)); | ||
674 | al->bulk_out = usb_sndbulkpipe(al->dev, | ||
675 | usb_endpoint_num(ep_out)); | ||
676 | |||
677 | /* second device is identical up to now */ | ||
678 | memcpy(al+1, al, sizeof(*al)); | ||
679 | |||
680 | mutex_init(&al[0].card_mutex); | ||
681 | mutex_init(&al[1].card_mutex); | ||
682 | |||
683 | al[0].port = ALAUDA_PORT_XD; | ||
684 | al[1].port = ALAUDA_PORT_SM; | ||
685 | |||
686 | dev_info(&interface->dev, "alauda probed\n"); | ||
687 | alauda_check_media(al); | ||
688 | alauda_check_media(al+1); | ||
689 | |||
690 | return 0; | ||
691 | |||
692 | error: | ||
693 | if (al) | ||
694 | kref_put(&al->kref, alauda_delete); | ||
695 | return err; | ||
696 | } | ||
697 | |||
698 | static void alauda_disconnect(struct usb_interface *interface) | ||
699 | { | ||
700 | struct alauda *al; | ||
701 | |||
702 | al = usb_get_intfdata(interface); | ||
703 | usb_set_intfdata(interface, NULL); | ||
704 | |||
705 | /* FIXME: prevent more I/O from starting */ | ||
706 | |||
707 | /* decrement our usage count */ | ||
708 | if (al) | ||
709 | kref_put(&al->kref, alauda_delete); | ||
710 | |||
711 | dev_info(&interface->dev, "alauda gone"); | ||
712 | } | ||
713 | |||
714 | static struct usb_driver alauda_driver = { | ||
715 | .name = "alauda", | ||
716 | .probe = alauda_probe, | ||
717 | .disconnect = alauda_disconnect, | ||
718 | .id_table = alauda_table, | ||
719 | }; | ||
720 | |||
721 | module_usb_driver(alauda_driver); | ||
722 | |||
723 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index f1d71cdc8aac..8611eb4b45fc 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c | |||
@@ -258,7 +258,6 @@ static int ams_delta_init(struct platform_device *pdev) | |||
258 | out_mtd: | 258 | out_mtd: |
259 | gpio_free_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio)); | 259 | gpio_free_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio)); |
260 | out_gpio: | 260 | out_gpio: |
261 | platform_set_drvdata(pdev, NULL); | ||
262 | gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB); | 261 | gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB); |
263 | iounmap(io_base); | 262 | iounmap(io_base); |
264 | out_free: | 263 | out_free: |
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 2d23d2929438..060feeaf6b3e 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
@@ -18,6 +18,9 @@ | |||
18 | * Add Programmable Multibit ECC support for various AT91 SoC | 18 | * Add Programmable Multibit ECC support for various AT91 SoC |
19 | * © Copyright 2012 ATMEL, Hong Xu | 19 | * © Copyright 2012 ATMEL, Hong Xu |
20 | * | 20 | * |
21 | * Add Nand Flash Controller support for SAMA5 SoC | ||
22 | * © Copyright 2013 ATMEL, Josh Wu (josh.wu@atmel.com) | ||
23 | * | ||
21 | * This program is free software; you can redistribute it and/or modify | 24 | * This program is free software; you can redistribute it and/or modify |
22 | * it under the terms of the GNU General Public License version 2 as | 25 | * it under the terms of the GNU General Public License version 2 as |
23 | * published by the Free Software Foundation. | 26 | * published by the Free Software Foundation. |
@@ -37,13 +40,12 @@ | |||
37 | #include <linux/mtd/nand.h> | 40 | #include <linux/mtd/nand.h> |
38 | #include <linux/mtd/partitions.h> | 41 | #include <linux/mtd/partitions.h> |
39 | 42 | ||
43 | #include <linux/delay.h> | ||
40 | #include <linux/dmaengine.h> | 44 | #include <linux/dmaengine.h> |
41 | #include <linux/gpio.h> | 45 | #include <linux/gpio.h> |
46 | #include <linux/interrupt.h> | ||
42 | #include <linux/io.h> | 47 | #include <linux/io.h> |
43 | #include <linux/platform_data/atmel.h> | 48 | #include <linux/platform_data/atmel.h> |
44 | #include <linux/pinctrl/consumer.h> | ||
45 | |||
46 | #include <mach/cpu.h> | ||
47 | 49 | ||
48 | static int use_dma = 1; | 50 | static int use_dma = 1; |
49 | module_param(use_dma, int, 0); | 51 | module_param(use_dma, int, 0); |
@@ -58,6 +60,7 @@ module_param(on_flash_bbt, int, 0); | |||
58 | __raw_writel((value), add + ATMEL_ECC_##reg) | 60 | __raw_writel((value), add + ATMEL_ECC_##reg) |
59 | 61 | ||
60 | #include "atmel_nand_ecc.h" /* Hardware ECC registers */ | 62 | #include "atmel_nand_ecc.h" /* Hardware ECC registers */ |
63 | #include "atmel_nand_nfc.h" /* Nand Flash Controller definition */ | ||
61 | 64 | ||
62 | /* oob layout for large page size | 65 | /* oob layout for large page size |
63 | * bad block info is on bytes 0 and 1 | 66 | * bad block info is on bytes 0 and 1 |
@@ -85,6 +88,23 @@ static struct nand_ecclayout atmel_oobinfo_small = { | |||
85 | }, | 88 | }, |
86 | }; | 89 | }; |
87 | 90 | ||
91 | struct atmel_nfc { | ||
92 | void __iomem *base_cmd_regs; | ||
93 | void __iomem *hsmc_regs; | ||
94 | void __iomem *sram_bank0; | ||
95 | dma_addr_t sram_bank0_phys; | ||
96 | bool use_nfc_sram; | ||
97 | bool write_by_sram; | ||
98 | |||
99 | bool is_initialized; | ||
100 | struct completion comp_nfc; | ||
101 | |||
102 | /* Point to the sram bank which include readed data via NFC */ | ||
103 | void __iomem *data_in_sram; | ||
104 | bool will_write_sram; | ||
105 | }; | ||
106 | static struct atmel_nfc nand_nfc; | ||
107 | |||
88 | struct atmel_nand_host { | 108 | struct atmel_nand_host { |
89 | struct nand_chip nand_chip; | 109 | struct nand_chip nand_chip; |
90 | struct mtd_info mtd; | 110 | struct mtd_info mtd; |
@@ -97,6 +117,8 @@ struct atmel_nand_host { | |||
97 | struct completion comp; | 117 | struct completion comp; |
98 | struct dma_chan *dma_chan; | 118 | struct dma_chan *dma_chan; |
99 | 119 | ||
120 | struct atmel_nfc *nfc; | ||
121 | |||
100 | bool has_pmecc; | 122 | bool has_pmecc; |
101 | u8 pmecc_corr_cap; | 123 | u8 pmecc_corr_cap; |
102 | u16 pmecc_sector_size; | 124 | u16 pmecc_sector_size; |
@@ -128,11 +150,6 @@ struct atmel_nand_host { | |||
128 | 150 | ||
129 | static struct nand_ecclayout atmel_pmecc_oobinfo; | 151 | static struct nand_ecclayout atmel_pmecc_oobinfo; |
130 | 152 | ||
131 | static int cpu_has_dma(void) | ||
132 | { | ||
133 | return cpu_is_at91sam9rl() || cpu_is_at91sam9g45(); | ||
134 | } | ||
135 | |||
136 | /* | 153 | /* |
137 | * Enable NAND. | 154 | * Enable NAND. |
138 | */ | 155 | */ |
@@ -186,21 +203,103 @@ static int atmel_nand_device_ready(struct mtd_info *mtd) | |||
186 | !!host->board.rdy_pin_active_low; | 203 | !!host->board.rdy_pin_active_low; |
187 | } | 204 | } |
188 | 205 | ||
206 | /* Set up for hardware ready pin and enable pin. */ | ||
207 | static int atmel_nand_set_enable_ready_pins(struct mtd_info *mtd) | ||
208 | { | ||
209 | struct nand_chip *chip = mtd->priv; | ||
210 | struct atmel_nand_host *host = chip->priv; | ||
211 | int res = 0; | ||
212 | |||
213 | if (gpio_is_valid(host->board.rdy_pin)) { | ||
214 | res = devm_gpio_request(host->dev, | ||
215 | host->board.rdy_pin, "nand_rdy"); | ||
216 | if (res < 0) { | ||
217 | dev_err(host->dev, | ||
218 | "can't request rdy gpio %d\n", | ||
219 | host->board.rdy_pin); | ||
220 | return res; | ||
221 | } | ||
222 | |||
223 | res = gpio_direction_input(host->board.rdy_pin); | ||
224 | if (res < 0) { | ||
225 | dev_err(host->dev, | ||
226 | "can't request input direction rdy gpio %d\n", | ||
227 | host->board.rdy_pin); | ||
228 | return res; | ||
229 | } | ||
230 | |||
231 | chip->dev_ready = atmel_nand_device_ready; | ||
232 | } | ||
233 | |||
234 | if (gpio_is_valid(host->board.enable_pin)) { | ||
235 | res = devm_gpio_request(host->dev, | ||
236 | host->board.enable_pin, "nand_enable"); | ||
237 | if (res < 0) { | ||
238 | dev_err(host->dev, | ||
239 | "can't request enable gpio %d\n", | ||
240 | host->board.enable_pin); | ||
241 | return res; | ||
242 | } | ||
243 | |||
244 | res = gpio_direction_output(host->board.enable_pin, 1); | ||
245 | if (res < 0) { | ||
246 | dev_err(host->dev, | ||
247 | "can't request output direction enable gpio %d\n", | ||
248 | host->board.enable_pin); | ||
249 | return res; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | return res; | ||
254 | } | ||
255 | |||
256 | static void memcpy32_fromio(void *trg, const void __iomem *src, size_t size) | ||
257 | { | ||
258 | int i; | ||
259 | u32 *t = trg; | ||
260 | const __iomem u32 *s = src; | ||
261 | |||
262 | for (i = 0; i < (size >> 2); i++) | ||
263 | *t++ = readl_relaxed(s++); | ||
264 | } | ||
265 | |||
266 | static void memcpy32_toio(void __iomem *trg, const void *src, int size) | ||
267 | { | ||
268 | int i; | ||
269 | u32 __iomem *t = trg; | ||
270 | const u32 *s = src; | ||
271 | |||
272 | for (i = 0; i < (size >> 2); i++) | ||
273 | writel_relaxed(*s++, t++); | ||
274 | } | ||
275 | |||
189 | /* | 276 | /* |
190 | * Minimal-overhead PIO for data access. | 277 | * Minimal-overhead PIO for data access. |
191 | */ | 278 | */ |
192 | static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len) | 279 | static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len) |
193 | { | 280 | { |
194 | struct nand_chip *nand_chip = mtd->priv; | 281 | struct nand_chip *nand_chip = mtd->priv; |
282 | struct atmel_nand_host *host = nand_chip->priv; | ||
195 | 283 | ||
196 | __raw_readsb(nand_chip->IO_ADDR_R, buf, len); | 284 | if (host->nfc && host->nfc->use_nfc_sram && host->nfc->data_in_sram) { |
285 | memcpy32_fromio(buf, host->nfc->data_in_sram, len); | ||
286 | host->nfc->data_in_sram += len; | ||
287 | } else { | ||
288 | __raw_readsb(nand_chip->IO_ADDR_R, buf, len); | ||
289 | } | ||
197 | } | 290 | } |
198 | 291 | ||
199 | static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len) | 292 | static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len) |
200 | { | 293 | { |
201 | struct nand_chip *nand_chip = mtd->priv; | 294 | struct nand_chip *nand_chip = mtd->priv; |
295 | struct atmel_nand_host *host = nand_chip->priv; | ||
202 | 296 | ||
203 | __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2); | 297 | if (host->nfc && host->nfc->use_nfc_sram && host->nfc->data_in_sram) { |
298 | memcpy32_fromio(buf, host->nfc->data_in_sram, len); | ||
299 | host->nfc->data_in_sram += len; | ||
300 | } else { | ||
301 | __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2); | ||
302 | } | ||
204 | } | 303 | } |
205 | 304 | ||
206 | static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len) | 305 | static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len) |
@@ -222,6 +321,40 @@ static void dma_complete_func(void *completion) | |||
222 | complete(completion); | 321 | complete(completion); |
223 | } | 322 | } |
224 | 323 | ||
324 | static int nfc_set_sram_bank(struct atmel_nand_host *host, unsigned int bank) | ||
325 | { | ||
326 | /* NFC only has two banks. Must be 0 or 1 */ | ||
327 | if (bank > 1) | ||
328 | return -EINVAL; | ||
329 | |||
330 | if (bank) { | ||
331 | /* Only for a 2k-page or lower flash, NFC can handle 2 banks */ | ||
332 | if (host->mtd.writesize > 2048) | ||
333 | return -EINVAL; | ||
334 | nfc_writel(host->nfc->hsmc_regs, BANK, ATMEL_HSMC_NFC_BANK1); | ||
335 | } else { | ||
336 | nfc_writel(host->nfc->hsmc_regs, BANK, ATMEL_HSMC_NFC_BANK0); | ||
337 | } | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static uint nfc_get_sram_off(struct atmel_nand_host *host) | ||
343 | { | ||
344 | if (nfc_readl(host->nfc->hsmc_regs, BANK) & ATMEL_HSMC_NFC_BANK1) | ||
345 | return NFC_SRAM_BANK1_OFFSET; | ||
346 | else | ||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | static dma_addr_t nfc_sram_phys(struct atmel_nand_host *host) | ||
351 | { | ||
352 | if (nfc_readl(host->nfc->hsmc_regs, BANK) & ATMEL_HSMC_NFC_BANK1) | ||
353 | return host->nfc->sram_bank0_phys + NFC_SRAM_BANK1_OFFSET; | ||
354 | else | ||
355 | return host->nfc->sram_bank0_phys; | ||
356 | } | ||
357 | |||
225 | static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len, | 358 | static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len, |
226 | int is_read) | 359 | int is_read) |
227 | { | 360 | { |
@@ -235,6 +368,7 @@ static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len, | |||
235 | void *p = buf; | 368 | void *p = buf; |
236 | int err = -EIO; | 369 | int err = -EIO; |
237 | enum dma_data_direction dir = is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | 370 | enum dma_data_direction dir = is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; |
371 | struct atmel_nfc *nfc = host->nfc; | ||
238 | 372 | ||
239 | if (buf >= high_memory) | 373 | if (buf >= high_memory) |
240 | goto err_buf; | 374 | goto err_buf; |
@@ -251,11 +385,20 @@ static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len, | |||
251 | } | 385 | } |
252 | 386 | ||
253 | if (is_read) { | 387 | if (is_read) { |
254 | dma_src_addr = host->io_phys; | 388 | if (nfc && nfc->data_in_sram) |
389 | dma_src_addr = nfc_sram_phys(host) + (nfc->data_in_sram | ||
390 | - (nfc->sram_bank0 + nfc_get_sram_off(host))); | ||
391 | else | ||
392 | dma_src_addr = host->io_phys; | ||
393 | |||
255 | dma_dst_addr = phys_addr; | 394 | dma_dst_addr = phys_addr; |
256 | } else { | 395 | } else { |
257 | dma_src_addr = phys_addr; | 396 | dma_src_addr = phys_addr; |
258 | dma_dst_addr = host->io_phys; | 397 | |
398 | if (nfc && nfc->write_by_sram) | ||
399 | dma_dst_addr = nfc_sram_phys(host); | ||
400 | else | ||
401 | dma_dst_addr = host->io_phys; | ||
259 | } | 402 | } |
260 | 403 | ||
261 | tx = dma_dev->device_prep_dma_memcpy(host->dma_chan, dma_dst_addr, | 404 | tx = dma_dev->device_prep_dma_memcpy(host->dma_chan, dma_dst_addr, |
@@ -278,6 +421,10 @@ static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len, | |||
278 | dma_async_issue_pending(host->dma_chan); | 421 | dma_async_issue_pending(host->dma_chan); |
279 | wait_for_completion(&host->comp); | 422 | wait_for_completion(&host->comp); |
280 | 423 | ||
424 | if (is_read && nfc && nfc->data_in_sram) | ||
425 | /* After read data from SRAM, need to increase the position */ | ||
426 | nfc->data_in_sram += len; | ||
427 | |||
281 | err = 0; | 428 | err = 0; |
282 | 429 | ||
283 | err_dma: | 430 | err_dma: |
@@ -366,43 +513,34 @@ static void __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host) | |||
366 | table_size * sizeof(int16_t); | 513 | table_size * sizeof(int16_t); |
367 | } | 514 | } |
368 | 515 | ||
369 | static void pmecc_data_free(struct atmel_nand_host *host) | ||
370 | { | ||
371 | kfree(host->pmecc_partial_syn); | ||
372 | kfree(host->pmecc_si); | ||
373 | kfree(host->pmecc_lmu); | ||
374 | kfree(host->pmecc_smu); | ||
375 | kfree(host->pmecc_mu); | ||
376 | kfree(host->pmecc_dmu); | ||
377 | kfree(host->pmecc_delta); | ||
378 | } | ||
379 | |||
380 | static int pmecc_data_alloc(struct atmel_nand_host *host) | 516 | static int pmecc_data_alloc(struct atmel_nand_host *host) |
381 | { | 517 | { |
382 | const int cap = host->pmecc_corr_cap; | 518 | const int cap = host->pmecc_corr_cap; |
519 | int size; | ||
520 | |||
521 | size = (2 * cap + 1) * sizeof(int16_t); | ||
522 | host->pmecc_partial_syn = devm_kzalloc(host->dev, size, GFP_KERNEL); | ||
523 | host->pmecc_si = devm_kzalloc(host->dev, size, GFP_KERNEL); | ||
524 | host->pmecc_lmu = devm_kzalloc(host->dev, | ||
525 | (cap + 1) * sizeof(int16_t), GFP_KERNEL); | ||
526 | host->pmecc_smu = devm_kzalloc(host->dev, | ||
527 | (cap + 2) * size, GFP_KERNEL); | ||
528 | |||
529 | size = (cap + 1) * sizeof(int); | ||
530 | host->pmecc_mu = devm_kzalloc(host->dev, size, GFP_KERNEL); | ||
531 | host->pmecc_dmu = devm_kzalloc(host->dev, size, GFP_KERNEL); | ||
532 | host->pmecc_delta = devm_kzalloc(host->dev, size, GFP_KERNEL); | ||
533 | |||
534 | if (!host->pmecc_partial_syn || | ||
535 | !host->pmecc_si || | ||
536 | !host->pmecc_lmu || | ||
537 | !host->pmecc_smu || | ||
538 | !host->pmecc_mu || | ||
539 | !host->pmecc_dmu || | ||
540 | !host->pmecc_delta) | ||
541 | return -ENOMEM; | ||
383 | 542 | ||
384 | host->pmecc_partial_syn = kzalloc((2 * cap + 1) * sizeof(int16_t), | 543 | return 0; |
385 | GFP_KERNEL); | ||
386 | host->pmecc_si = kzalloc((2 * cap + 1) * sizeof(int16_t), GFP_KERNEL); | ||
387 | host->pmecc_lmu = kzalloc((cap + 1) * sizeof(int16_t), GFP_KERNEL); | ||
388 | host->pmecc_smu = kzalloc((cap + 2) * (2 * cap + 1) * sizeof(int16_t), | ||
389 | GFP_KERNEL); | ||
390 | host->pmecc_mu = kzalloc((cap + 1) * sizeof(int), GFP_KERNEL); | ||
391 | host->pmecc_dmu = kzalloc((cap + 1) * sizeof(int), GFP_KERNEL); | ||
392 | host->pmecc_delta = kzalloc((cap + 1) * sizeof(int), GFP_KERNEL); | ||
393 | |||
394 | if (host->pmecc_partial_syn && | ||
395 | host->pmecc_si && | ||
396 | host->pmecc_lmu && | ||
397 | host->pmecc_smu && | ||
398 | host->pmecc_mu && | ||
399 | host->pmecc_dmu && | ||
400 | host->pmecc_delta) | ||
401 | return 0; | ||
402 | |||
403 | /* error happened */ | ||
404 | pmecc_data_free(host); | ||
405 | return -ENOMEM; | ||
406 | } | 544 | } |
407 | 545 | ||
408 | static void pmecc_gen_syndrome(struct mtd_info *mtd, int sector) | 546 | static void pmecc_gen_syndrome(struct mtd_info *mtd, int sector) |
@@ -763,6 +901,30 @@ normal_check: | |||
763 | return total_err; | 901 | return total_err; |
764 | } | 902 | } |
765 | 903 | ||
904 | static void pmecc_enable(struct atmel_nand_host *host, int ecc_op) | ||
905 | { | ||
906 | u32 val; | ||
907 | |||
908 | if (ecc_op != NAND_ECC_READ && ecc_op != NAND_ECC_WRITE) { | ||
909 | dev_err(host->dev, "atmel_nand: wrong pmecc operation type!"); | ||
910 | return; | ||
911 | } | ||
912 | |||
913 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST); | ||
914 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); | ||
915 | val = pmecc_readl_relaxed(host->ecc, CFG); | ||
916 | |||
917 | if (ecc_op == NAND_ECC_READ) | ||
918 | pmecc_writel(host->ecc, CFG, (val & ~PMECC_CFG_WRITE_OP) | ||
919 | | PMECC_CFG_AUTO_ENABLE); | ||
920 | else | ||
921 | pmecc_writel(host->ecc, CFG, (val | PMECC_CFG_WRITE_OP) | ||
922 | & ~PMECC_CFG_AUTO_ENABLE); | ||
923 | |||
924 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE); | ||
925 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DATA); | ||
926 | } | ||
927 | |||
766 | static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, | 928 | static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, |
767 | struct nand_chip *chip, uint8_t *buf, int oob_required, int page) | 929 | struct nand_chip *chip, uint8_t *buf, int oob_required, int page) |
768 | { | 930 | { |
@@ -774,13 +936,8 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, | |||
774 | unsigned long end_time; | 936 | unsigned long end_time; |
775 | int bitflips = 0; | 937 | int bitflips = 0; |
776 | 938 | ||
777 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST); | 939 | if (!host->nfc || !host->nfc->use_nfc_sram) |
778 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); | 940 | pmecc_enable(host, NAND_ECC_READ); |
779 | pmecc_writel(host->ecc, CFG, (pmecc_readl_relaxed(host->ecc, CFG) | ||
780 | & ~PMECC_CFG_WRITE_OP) | PMECC_CFG_AUTO_ENABLE); | ||
781 | |||
782 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE); | ||
783 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DATA); | ||
784 | 941 | ||
785 | chip->read_buf(mtd, buf, eccsize); | 942 | chip->read_buf(mtd, buf, eccsize); |
786 | chip->read_buf(mtd, oob, mtd->oobsize); | 943 | chip->read_buf(mtd, oob, mtd->oobsize); |
@@ -813,16 +970,10 @@ static int atmel_nand_pmecc_write_page(struct mtd_info *mtd, | |||
813 | int i, j; | 970 | int i, j; |
814 | unsigned long end_time; | 971 | unsigned long end_time; |
815 | 972 | ||
816 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST); | 973 | if (!host->nfc || !host->nfc->write_by_sram) { |
817 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); | 974 | pmecc_enable(host, NAND_ECC_WRITE); |
818 | 975 | chip->write_buf(mtd, (u8 *)buf, mtd->writesize); | |
819 | pmecc_writel(host->ecc, CFG, (pmecc_readl_relaxed(host->ecc, CFG) | | 976 | } |
820 | PMECC_CFG_WRITE_OP) & ~PMECC_CFG_AUTO_ENABLE); | ||
821 | |||
822 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE); | ||
823 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DATA); | ||
824 | |||
825 | chip->write_buf(mtd, (u8 *)buf, mtd->writesize); | ||
826 | 977 | ||
827 | end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS); | 978 | end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS); |
828 | while ((pmecc_readl_relaxed(host->ecc, SR) & PMECC_SR_BUSY)) { | 979 | while ((pmecc_readl_relaxed(host->ecc, SR) & PMECC_SR_BUSY)) { |
@@ -967,11 +1118,11 @@ static int pmecc_choose_ecc(struct atmel_nand_host *host, | |||
967 | host->pmecc_corr_cap = 2; | 1118 | host->pmecc_corr_cap = 2; |
968 | else if (*cap <= 4) | 1119 | else if (*cap <= 4) |
969 | host->pmecc_corr_cap = 4; | 1120 | host->pmecc_corr_cap = 4; |
970 | else if (*cap < 8) | 1121 | else if (*cap <= 8) |
971 | host->pmecc_corr_cap = 8; | 1122 | host->pmecc_corr_cap = 8; |
972 | else if (*cap < 12) | 1123 | else if (*cap <= 12) |
973 | host->pmecc_corr_cap = 12; | 1124 | host->pmecc_corr_cap = 12; |
974 | else if (*cap < 24) | 1125 | else if (*cap <= 24) |
975 | host->pmecc_corr_cap = 24; | 1126 | host->pmecc_corr_cap = 24; |
976 | else | 1127 | else |
977 | return -EINVAL; | 1128 | return -EINVAL; |
@@ -1002,7 +1153,7 @@ static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev, | |||
1002 | return err_no; | 1153 | return err_no; |
1003 | } | 1154 | } |
1004 | 1155 | ||
1005 | if (cap != host->pmecc_corr_cap || | 1156 | if (cap > host->pmecc_corr_cap || |
1006 | sector_size != host->pmecc_sector_size) | 1157 | sector_size != host->pmecc_sector_size) |
1007 | dev_info(host->dev, "WARNING: Be Caution! Using different PMECC parameters from Nand ONFI ECC reqirement.\n"); | 1158 | dev_info(host->dev, "WARNING: Be Caution! Using different PMECC parameters from Nand ONFI ECC reqirement.\n"); |
1008 | 1159 | ||
@@ -1023,27 +1174,28 @@ static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev, | |||
1023 | return 0; | 1174 | return 0; |
1024 | } | 1175 | } |
1025 | 1176 | ||
1026 | host->ecc = ioremap(regs->start, resource_size(regs)); | 1177 | host->ecc = devm_ioremap_resource(&pdev->dev, regs); |
1027 | if (host->ecc == NULL) { | 1178 | if (IS_ERR(host->ecc)) { |
1028 | dev_err(host->dev, "ioremap failed\n"); | 1179 | dev_err(host->dev, "ioremap failed\n"); |
1029 | err_no = -EIO; | 1180 | err_no = PTR_ERR(host->ecc); |
1030 | goto err_pmecc_ioremap; | 1181 | goto err; |
1031 | } | 1182 | } |
1032 | 1183 | ||
1033 | regs_pmerr = platform_get_resource(pdev, IORESOURCE_MEM, 2); | 1184 | regs_pmerr = platform_get_resource(pdev, IORESOURCE_MEM, 2); |
1034 | regs_rom = platform_get_resource(pdev, IORESOURCE_MEM, 3); | 1185 | host->pmerrloc_base = devm_ioremap_resource(&pdev->dev, regs_pmerr); |
1035 | if (regs_pmerr && regs_rom) { | 1186 | if (IS_ERR(host->pmerrloc_base)) { |
1036 | host->pmerrloc_base = ioremap(regs_pmerr->start, | 1187 | dev_err(host->dev, |
1037 | resource_size(regs_pmerr)); | 1188 | "Can not get I/O resource for PMECC ERRLOC controller!\n"); |
1038 | host->pmecc_rom_base = ioremap(regs_rom->start, | 1189 | err_no = PTR_ERR(host->pmerrloc_base); |
1039 | resource_size(regs_rom)); | 1190 | goto err; |
1040 | } | 1191 | } |
1041 | 1192 | ||
1042 | if (!host->pmerrloc_base || !host->pmecc_rom_base) { | 1193 | regs_rom = platform_get_resource(pdev, IORESOURCE_MEM, 3); |
1043 | dev_err(host->dev, | 1194 | host->pmecc_rom_base = devm_ioremap_resource(&pdev->dev, regs_rom); |
1044 | "Can not get I/O resource for PMECC ERRLOC controller or ROM!\n"); | 1195 | if (IS_ERR(host->pmecc_rom_base)) { |
1045 | err_no = -EIO; | 1196 | dev_err(host->dev, "Can not get I/O resource for ROM!\n"); |
1046 | goto err_pmloc_ioremap; | 1197 | err_no = PTR_ERR(host->pmecc_rom_base); |
1198 | goto err; | ||
1047 | } | 1199 | } |
1048 | 1200 | ||
1049 | /* ECC is calculated for the whole page (1 step) */ | 1201 | /* ECC is calculated for the whole page (1 step) */ |
@@ -1052,7 +1204,8 @@ static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev, | |||
1052 | /* set ECC page size and oob layout */ | 1204 | /* set ECC page size and oob layout */ |
1053 | switch (mtd->writesize) { | 1205 | switch (mtd->writesize) { |
1054 | case 2048: | 1206 | case 2048: |
1055 | host->pmecc_degree = PMECC_GF_DIMENSION_13; | 1207 | host->pmecc_degree = (sector_size == 512) ? |
1208 | PMECC_GF_DIMENSION_13 : PMECC_GF_DIMENSION_14; | ||
1056 | host->pmecc_cw_len = (1 << host->pmecc_degree) - 1; | 1209 | host->pmecc_cw_len = (1 << host->pmecc_degree) - 1; |
1057 | host->pmecc_sector_number = mtd->writesize / sector_size; | 1210 | host->pmecc_sector_number = mtd->writesize / sector_size; |
1058 | host->pmecc_bytes_per_sector = pmecc_get_ecc_bytes( | 1211 | host->pmecc_bytes_per_sector = pmecc_get_ecc_bytes( |
@@ -1068,7 +1221,7 @@ static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev, | |||
1068 | if (nand_chip->ecc.bytes > mtd->oobsize - 2) { | 1221 | if (nand_chip->ecc.bytes > mtd->oobsize - 2) { |
1069 | dev_err(host->dev, "No room for ECC bytes\n"); | 1222 | dev_err(host->dev, "No room for ECC bytes\n"); |
1070 | err_no = -EINVAL; | 1223 | err_no = -EINVAL; |
1071 | goto err_no_ecc_room; | 1224 | goto err; |
1072 | } | 1225 | } |
1073 | pmecc_config_ecc_layout(&atmel_pmecc_oobinfo, | 1226 | pmecc_config_ecc_layout(&atmel_pmecc_oobinfo, |
1074 | mtd->oobsize, | 1227 | mtd->oobsize, |
@@ -1093,7 +1246,7 @@ static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev, | |||
1093 | if (err_no) { | 1246 | if (err_no) { |
1094 | dev_err(host->dev, | 1247 | dev_err(host->dev, |
1095 | "Cannot allocate memory for PMECC computation!\n"); | 1248 | "Cannot allocate memory for PMECC computation!\n"); |
1096 | goto err_pmecc_data_alloc; | 1249 | goto err; |
1097 | } | 1250 | } |
1098 | 1251 | ||
1099 | nand_chip->ecc.read_page = atmel_nand_pmecc_read_page; | 1252 | nand_chip->ecc.read_page = atmel_nand_pmecc_read_page; |
@@ -1103,15 +1256,7 @@ static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev, | |||
1103 | 1256 | ||
1104 | return 0; | 1257 | return 0; |
1105 | 1258 | ||
1106 | err_pmecc_data_alloc: | 1259 | err: |
1107 | err_no_ecc_room: | ||
1108 | err_pmloc_ioremap: | ||
1109 | iounmap(host->ecc); | ||
1110 | if (host->pmerrloc_base) | ||
1111 | iounmap(host->pmerrloc_base); | ||
1112 | if (host->pmecc_rom_base) | ||
1113 | iounmap(host->pmecc_rom_base); | ||
1114 | err_pmecc_ioremap: | ||
1115 | return err_no; | 1260 | return err_no; |
1116 | } | 1261 | } |
1117 | 1262 | ||
@@ -1174,10 +1319,9 @@ static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
1174 | * Workaround: Reset the parity registers before reading the | 1319 | * Workaround: Reset the parity registers before reading the |
1175 | * actual data. | 1320 | * actual data. |
1176 | */ | 1321 | */ |
1177 | if (cpu_is_at32ap7000()) { | 1322 | struct atmel_nand_host *host = chip->priv; |
1178 | struct atmel_nand_host *host = chip->priv; | 1323 | if (host->board.need_reset_workaround) |
1179 | ecc_writel(host->ecc, CR, ATMEL_ECC_RST); | 1324 | ecc_writel(host->ecc, CR, ATMEL_ECC_RST); |
1180 | } | ||
1181 | 1325 | ||
1182 | /* read the page */ | 1326 | /* read the page */ |
1183 | chip->read_buf(mtd, p, eccsize); | 1327 | chip->read_buf(mtd, p, eccsize); |
@@ -1298,11 +1442,11 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat, | |||
1298 | */ | 1442 | */ |
1299 | static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) | 1443 | static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) |
1300 | { | 1444 | { |
1301 | if (cpu_is_at32ap7000()) { | 1445 | struct nand_chip *nand_chip = mtd->priv; |
1302 | struct nand_chip *nand_chip = mtd->priv; | 1446 | struct atmel_nand_host *host = nand_chip->priv; |
1303 | struct atmel_nand_host *host = nand_chip->priv; | 1447 | |
1448 | if (host->board.need_reset_workaround) | ||
1304 | ecc_writel(host->ecc, CR, ATMEL_ECC_RST); | 1449 | ecc_writel(host->ecc, CR, ATMEL_ECC_RST); |
1305 | } | ||
1306 | } | 1450 | } |
1307 | 1451 | ||
1308 | #if defined(CONFIG_OF) | 1452 | #if defined(CONFIG_OF) |
@@ -1337,6 +1481,8 @@ static int atmel_of_init_port(struct atmel_nand_host *host, | |||
1337 | 1481 | ||
1338 | board->on_flash_bbt = of_get_nand_on_flash_bbt(np); | 1482 | board->on_flash_bbt = of_get_nand_on_flash_bbt(np); |
1339 | 1483 | ||
1484 | board->has_dma = of_property_read_bool(np, "atmel,nand-has-dma"); | ||
1485 | |||
1340 | if (of_get_nand_bus_width(np) == 16) | 1486 | if (of_get_nand_bus_width(np) == 16) |
1341 | board->bus_width_16 = 1; | 1487 | board->bus_width_16 = 1; |
1342 | 1488 | ||
@@ -1348,6 +1494,9 @@ static int atmel_of_init_port(struct atmel_nand_host *host, | |||
1348 | 1494 | ||
1349 | host->has_pmecc = of_property_read_bool(np, "atmel,has-pmecc"); | 1495 | host->has_pmecc = of_property_read_bool(np, "atmel,has-pmecc"); |
1350 | 1496 | ||
1497 | /* load the nfc driver if there is */ | ||
1498 | of_platform_populate(np, NULL, NULL, host->dev); | ||
1499 | |||
1351 | if (!(board->ecc_mode == NAND_ECC_HW) || !host->has_pmecc) | 1500 | if (!(board->ecc_mode == NAND_ECC_HW) || !host->has_pmecc) |
1352 | return 0; /* Not using PMECC */ | 1501 | return 0; /* Not using PMECC */ |
1353 | 1502 | ||
@@ -1414,10 +1563,10 @@ static int __init atmel_hw_nand_init_params(struct platform_device *pdev, | |||
1414 | return 0; | 1563 | return 0; |
1415 | } | 1564 | } |
1416 | 1565 | ||
1417 | host->ecc = ioremap(regs->start, resource_size(regs)); | 1566 | host->ecc = devm_ioremap_resource(&pdev->dev, regs); |
1418 | if (host->ecc == NULL) { | 1567 | if (IS_ERR(host->ecc)) { |
1419 | dev_err(host->dev, "ioremap failed\n"); | 1568 | dev_err(host->dev, "ioremap failed\n"); |
1420 | return -EIO; | 1569 | return PTR_ERR(host->ecc); |
1421 | } | 1570 | } |
1422 | 1571 | ||
1423 | /* ECC is calculated for the whole page (1 step) */ | 1572 | /* ECC is calculated for the whole page (1 step) */ |
@@ -1459,6 +1608,382 @@ static int __init atmel_hw_nand_init_params(struct platform_device *pdev, | |||
1459 | return 0; | 1608 | return 0; |
1460 | } | 1609 | } |
1461 | 1610 | ||
1611 | /* SMC interrupt service routine */ | ||
1612 | static irqreturn_t hsmc_interrupt(int irq, void *dev_id) | ||
1613 | { | ||
1614 | struct atmel_nand_host *host = dev_id; | ||
1615 | u32 status, mask, pending; | ||
1616 | irqreturn_t ret = IRQ_HANDLED; | ||
1617 | |||
1618 | status = nfc_readl(host->nfc->hsmc_regs, SR); | ||
1619 | mask = nfc_readl(host->nfc->hsmc_regs, IMR); | ||
1620 | pending = status & mask; | ||
1621 | |||
1622 | if (pending & NFC_SR_XFR_DONE) { | ||
1623 | complete(&host->nfc->comp_nfc); | ||
1624 | nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_XFR_DONE); | ||
1625 | } else if (pending & NFC_SR_RB_EDGE) { | ||
1626 | complete(&host->nfc->comp_nfc); | ||
1627 | nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_RB_EDGE); | ||
1628 | } else if (pending & NFC_SR_CMD_DONE) { | ||
1629 | complete(&host->nfc->comp_nfc); | ||
1630 | nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_CMD_DONE); | ||
1631 | } else { | ||
1632 | ret = IRQ_NONE; | ||
1633 | } | ||
1634 | |||
1635 | return ret; | ||
1636 | } | ||
1637 | |||
1638 | /* NFC(Nand Flash Controller) related functions */ | ||
1639 | static int nfc_wait_interrupt(struct atmel_nand_host *host, u32 flag) | ||
1640 | { | ||
1641 | unsigned long timeout; | ||
1642 | init_completion(&host->nfc->comp_nfc); | ||
1643 | |||
1644 | /* Enable interrupt that need to wait for */ | ||
1645 | nfc_writel(host->nfc->hsmc_regs, IER, flag); | ||
1646 | |||
1647 | timeout = wait_for_completion_timeout(&host->nfc->comp_nfc, | ||
1648 | msecs_to_jiffies(NFC_TIME_OUT_MS)); | ||
1649 | if (timeout) | ||
1650 | return 0; | ||
1651 | |||
1652 | /* Time out to wait for the interrupt */ | ||
1653 | dev_err(host->dev, "Time out to wait for interrupt: 0x%08x\n", flag); | ||
1654 | return -ETIMEDOUT; | ||
1655 | } | ||
1656 | |||
1657 | static int nfc_send_command(struct atmel_nand_host *host, | ||
1658 | unsigned int cmd, unsigned int addr, unsigned char cycle0) | ||
1659 | { | ||
1660 | unsigned long timeout; | ||
1661 | dev_dbg(host->dev, | ||
1662 | "nfc_cmd: 0x%08x, addr1234: 0x%08x, cycle0: 0x%02x\n", | ||
1663 | cmd, addr, cycle0); | ||
1664 | |||
1665 | timeout = jiffies + msecs_to_jiffies(NFC_TIME_OUT_MS); | ||
1666 | while (nfc_cmd_readl(NFCADDR_CMD_NFCBUSY, host->nfc->base_cmd_regs) | ||
1667 | & NFCADDR_CMD_NFCBUSY) { | ||
1668 | if (time_after(jiffies, timeout)) { | ||
1669 | dev_err(host->dev, | ||
1670 | "Time out to wait CMD_NFCBUSY ready!\n"); | ||
1671 | return -ETIMEDOUT; | ||
1672 | } | ||
1673 | } | ||
1674 | nfc_writel(host->nfc->hsmc_regs, CYCLE0, cycle0); | ||
1675 | nfc_cmd_addr1234_writel(cmd, addr, host->nfc->base_cmd_regs); | ||
1676 | return nfc_wait_interrupt(host, NFC_SR_CMD_DONE); | ||
1677 | } | ||
1678 | |||
1679 | static int nfc_device_ready(struct mtd_info *mtd) | ||
1680 | { | ||
1681 | struct nand_chip *nand_chip = mtd->priv; | ||
1682 | struct atmel_nand_host *host = nand_chip->priv; | ||
1683 | if (!nfc_wait_interrupt(host, NFC_SR_RB_EDGE)) | ||
1684 | return 1; | ||
1685 | return 0; | ||
1686 | } | ||
1687 | |||
1688 | static void nfc_select_chip(struct mtd_info *mtd, int chip) | ||
1689 | { | ||
1690 | struct nand_chip *nand_chip = mtd->priv; | ||
1691 | struct atmel_nand_host *host = nand_chip->priv; | ||
1692 | |||
1693 | if (chip == -1) | ||
1694 | nfc_writel(host->nfc->hsmc_regs, CTRL, NFC_CTRL_DISABLE); | ||
1695 | else | ||
1696 | nfc_writel(host->nfc->hsmc_regs, CTRL, NFC_CTRL_ENABLE); | ||
1697 | } | ||
1698 | |||
1699 | static int nfc_make_addr(struct mtd_info *mtd, int column, int page_addr, | ||
1700 | unsigned int *addr1234, unsigned int *cycle0) | ||
1701 | { | ||
1702 | struct nand_chip *chip = mtd->priv; | ||
1703 | |||
1704 | int acycle = 0; | ||
1705 | unsigned char addr_bytes[8]; | ||
1706 | int index = 0, bit_shift; | ||
1707 | |||
1708 | BUG_ON(addr1234 == NULL || cycle0 == NULL); | ||
1709 | |||
1710 | *cycle0 = 0; | ||
1711 | *addr1234 = 0; | ||
1712 | |||
1713 | if (column != -1) { | ||
1714 | if (chip->options & NAND_BUSWIDTH_16) | ||
1715 | column >>= 1; | ||
1716 | addr_bytes[acycle++] = column & 0xff; | ||
1717 | if (mtd->writesize > 512) | ||
1718 | addr_bytes[acycle++] = (column >> 8) & 0xff; | ||
1719 | } | ||
1720 | |||
1721 | if (page_addr != -1) { | ||
1722 | addr_bytes[acycle++] = page_addr & 0xff; | ||
1723 | addr_bytes[acycle++] = (page_addr >> 8) & 0xff; | ||
1724 | if (chip->chipsize > (128 << 20)) | ||
1725 | addr_bytes[acycle++] = (page_addr >> 16) & 0xff; | ||
1726 | } | ||
1727 | |||
1728 | if (acycle > 4) | ||
1729 | *cycle0 = addr_bytes[index++]; | ||
1730 | |||
1731 | for (bit_shift = 0; index < acycle; bit_shift += 8) | ||
1732 | *addr1234 += addr_bytes[index++] << bit_shift; | ||
1733 | |||
1734 | /* return acycle in cmd register */ | ||
1735 | return acycle << NFCADDR_CMD_ACYCLE_BIT_POS; | ||
1736 | } | ||
1737 | |||
1738 | static void nfc_nand_command(struct mtd_info *mtd, unsigned int command, | ||
1739 | int column, int page_addr) | ||
1740 | { | ||
1741 | struct nand_chip *chip = mtd->priv; | ||
1742 | struct atmel_nand_host *host = chip->priv; | ||
1743 | unsigned long timeout; | ||
1744 | unsigned int nfc_addr_cmd = 0; | ||
1745 | |||
1746 | unsigned int cmd1 = command << NFCADDR_CMD_CMD1_BIT_POS; | ||
1747 | |||
1748 | /* Set default settings: no cmd2, no addr cycle. read from nand */ | ||
1749 | unsigned int cmd2 = 0; | ||
1750 | unsigned int vcmd2 = 0; | ||
1751 | int acycle = NFCADDR_CMD_ACYCLE_NONE; | ||
1752 | int csid = NFCADDR_CMD_CSID_3; | ||
1753 | int dataen = NFCADDR_CMD_DATADIS; | ||
1754 | int nfcwr = NFCADDR_CMD_NFCRD; | ||
1755 | unsigned int addr1234 = 0; | ||
1756 | unsigned int cycle0 = 0; | ||
1757 | bool do_addr = true; | ||
1758 | host->nfc->data_in_sram = NULL; | ||
1759 | |||
1760 | dev_dbg(host->dev, "%s: cmd = 0x%02x, col = 0x%08x, page = 0x%08x\n", | ||
1761 | __func__, command, column, page_addr); | ||
1762 | |||
1763 | switch (command) { | ||
1764 | case NAND_CMD_RESET: | ||
1765 | nfc_addr_cmd = cmd1 | acycle | csid | dataen | nfcwr; | ||
1766 | nfc_send_command(host, nfc_addr_cmd, addr1234, cycle0); | ||
1767 | udelay(chip->chip_delay); | ||
1768 | |||
1769 | nfc_nand_command(mtd, NAND_CMD_STATUS, -1, -1); | ||
1770 | timeout = jiffies + msecs_to_jiffies(NFC_TIME_OUT_MS); | ||
1771 | while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) { | ||
1772 | if (time_after(jiffies, timeout)) { | ||
1773 | dev_err(host->dev, | ||
1774 | "Time out to wait status ready!\n"); | ||
1775 | break; | ||
1776 | } | ||
1777 | } | ||
1778 | return; | ||
1779 | case NAND_CMD_STATUS: | ||
1780 | do_addr = false; | ||
1781 | break; | ||
1782 | case NAND_CMD_PARAM: | ||
1783 | case NAND_CMD_READID: | ||
1784 | do_addr = false; | ||
1785 | acycle = NFCADDR_CMD_ACYCLE_1; | ||
1786 | if (column != -1) | ||
1787 | addr1234 = column; | ||
1788 | break; | ||
1789 | case NAND_CMD_RNDOUT: | ||
1790 | cmd2 = NAND_CMD_RNDOUTSTART << NFCADDR_CMD_CMD2_BIT_POS; | ||
1791 | vcmd2 = NFCADDR_CMD_VCMD2; | ||
1792 | break; | ||
1793 | case NAND_CMD_READ0: | ||
1794 | case NAND_CMD_READOOB: | ||
1795 | if (command == NAND_CMD_READOOB) { | ||
1796 | column += mtd->writesize; | ||
1797 | command = NAND_CMD_READ0; /* only READ0 is valid */ | ||
1798 | cmd1 = command << NFCADDR_CMD_CMD1_BIT_POS; | ||
1799 | } | ||
1800 | if (host->nfc->use_nfc_sram) { | ||
1801 | /* Enable Data transfer to sram */ | ||
1802 | dataen = NFCADDR_CMD_DATAEN; | ||
1803 | |||
1804 | /* Need enable PMECC now, since NFC will transfer | ||
1805 | * data in bus after sending nfc read command. | ||
1806 | */ | ||
1807 | if (chip->ecc.mode == NAND_ECC_HW && host->has_pmecc) | ||
1808 | pmecc_enable(host, NAND_ECC_READ); | ||
1809 | } | ||
1810 | |||
1811 | cmd2 = NAND_CMD_READSTART << NFCADDR_CMD_CMD2_BIT_POS; | ||
1812 | vcmd2 = NFCADDR_CMD_VCMD2; | ||
1813 | break; | ||
1814 | /* For prgramming command, the cmd need set to write enable */ | ||
1815 | case NAND_CMD_PAGEPROG: | ||
1816 | case NAND_CMD_SEQIN: | ||
1817 | case NAND_CMD_RNDIN: | ||
1818 | nfcwr = NFCADDR_CMD_NFCWR; | ||
1819 | if (host->nfc->will_write_sram && command == NAND_CMD_SEQIN) | ||
1820 | dataen = NFCADDR_CMD_DATAEN; | ||
1821 | break; | ||
1822 | default: | ||
1823 | break; | ||
1824 | } | ||
1825 | |||
1826 | if (do_addr) | ||
1827 | acycle = nfc_make_addr(mtd, column, page_addr, &addr1234, | ||
1828 | &cycle0); | ||
1829 | |||
1830 | nfc_addr_cmd = cmd1 | cmd2 | vcmd2 | acycle | csid | dataen | nfcwr; | ||
1831 | nfc_send_command(host, nfc_addr_cmd, addr1234, cycle0); | ||
1832 | |||
1833 | if (dataen == NFCADDR_CMD_DATAEN) | ||
1834 | if (nfc_wait_interrupt(host, NFC_SR_XFR_DONE)) | ||
1835 | dev_err(host->dev, "something wrong, No XFR_DONE interrupt comes.\n"); | ||
1836 | |||
1837 | /* | ||
1838 | * Program and erase have their own busy handlers status, sequential | ||
1839 | * in, and deplete1 need no delay. | ||
1840 | */ | ||
1841 | switch (command) { | ||
1842 | case NAND_CMD_CACHEDPROG: | ||
1843 | case NAND_CMD_PAGEPROG: | ||
1844 | case NAND_CMD_ERASE1: | ||
1845 | case NAND_CMD_ERASE2: | ||
1846 | case NAND_CMD_RNDIN: | ||
1847 | case NAND_CMD_STATUS: | ||
1848 | case NAND_CMD_RNDOUT: | ||
1849 | case NAND_CMD_SEQIN: | ||
1850 | case NAND_CMD_READID: | ||
1851 | return; | ||
1852 | |||
1853 | case NAND_CMD_READ0: | ||
1854 | if (dataen == NFCADDR_CMD_DATAEN) { | ||
1855 | host->nfc->data_in_sram = host->nfc->sram_bank0 + | ||
1856 | nfc_get_sram_off(host); | ||
1857 | return; | ||
1858 | } | ||
1859 | /* fall through */ | ||
1860 | default: | ||
1861 | nfc_wait_interrupt(host, NFC_SR_RB_EDGE); | ||
1862 | } | ||
1863 | } | ||
1864 | |||
1865 | static int nfc_sram_write_page(struct mtd_info *mtd, struct nand_chip *chip, | ||
1866 | uint32_t offset, int data_len, const uint8_t *buf, | ||
1867 | int oob_required, int page, int cached, int raw) | ||
1868 | { | ||
1869 | int cfg, len; | ||
1870 | int status = 0; | ||
1871 | struct atmel_nand_host *host = chip->priv; | ||
1872 | void __iomem *sram = host->nfc->sram_bank0 + nfc_get_sram_off(host); | ||
1873 | |||
1874 | /* Subpage write is not supported */ | ||
1875 | if (offset || (data_len < mtd->writesize)) | ||
1876 | return -EINVAL; | ||
1877 | |||
1878 | cfg = nfc_readl(host->nfc->hsmc_regs, CFG); | ||
1879 | len = mtd->writesize; | ||
1880 | |||
1881 | if (unlikely(raw)) { | ||
1882 | len += mtd->oobsize; | ||
1883 | nfc_writel(host->nfc->hsmc_regs, CFG, cfg | NFC_CFG_WSPARE); | ||
1884 | } else | ||
1885 | nfc_writel(host->nfc->hsmc_regs, CFG, cfg & ~NFC_CFG_WSPARE); | ||
1886 | |||
1887 | /* Copy page data to sram that will write to nand via NFC */ | ||
1888 | if (use_dma) { | ||
1889 | if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) != 0) | ||
1890 | /* Fall back to use cpu copy */ | ||
1891 | memcpy32_toio(sram, buf, len); | ||
1892 | } else { | ||
1893 | memcpy32_toio(sram, buf, len); | ||
1894 | } | ||
1895 | |||
1896 | if (chip->ecc.mode == NAND_ECC_HW && host->has_pmecc) | ||
1897 | /* | ||
1898 | * When use NFC sram, need set up PMECC before send | ||
1899 | * NAND_CMD_SEQIN command. Since when the nand command | ||
1900 | * is sent, nfc will do transfer from sram and nand. | ||
1901 | */ | ||
1902 | pmecc_enable(host, NAND_ECC_WRITE); | ||
1903 | |||
1904 | host->nfc->will_write_sram = true; | ||
1905 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); | ||
1906 | host->nfc->will_write_sram = false; | ||
1907 | |||
1908 | if (likely(!raw)) | ||
1909 | /* Need to write ecc into oob */ | ||
1910 | status = chip->ecc.write_page(mtd, chip, buf, oob_required); | ||
1911 | |||
1912 | if (status < 0) | ||
1913 | return status; | ||
1914 | |||
1915 | chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); | ||
1916 | status = chip->waitfunc(mtd, chip); | ||
1917 | |||
1918 | if ((status & NAND_STATUS_FAIL) && (chip->errstat)) | ||
1919 | status = chip->errstat(mtd, chip, FL_WRITING, status, page); | ||
1920 | |||
1921 | if (status & NAND_STATUS_FAIL) | ||
1922 | return -EIO; | ||
1923 | |||
1924 | return 0; | ||
1925 | } | ||
1926 | |||
1927 | static int nfc_sram_init(struct mtd_info *mtd) | ||
1928 | { | ||
1929 | struct nand_chip *chip = mtd->priv; | ||
1930 | struct atmel_nand_host *host = chip->priv; | ||
1931 | int res = 0; | ||
1932 | |||
1933 | /* Initialize the NFC CFG register */ | ||
1934 | unsigned int cfg_nfc = 0; | ||
1935 | |||
1936 | /* set page size and oob layout */ | ||
1937 | switch (mtd->writesize) { | ||
1938 | case 512: | ||
1939 | cfg_nfc = NFC_CFG_PAGESIZE_512; | ||
1940 | break; | ||
1941 | case 1024: | ||
1942 | cfg_nfc = NFC_CFG_PAGESIZE_1024; | ||
1943 | break; | ||
1944 | case 2048: | ||
1945 | cfg_nfc = NFC_CFG_PAGESIZE_2048; | ||
1946 | break; | ||
1947 | case 4096: | ||
1948 | cfg_nfc = NFC_CFG_PAGESIZE_4096; | ||
1949 | break; | ||
1950 | case 8192: | ||
1951 | cfg_nfc = NFC_CFG_PAGESIZE_8192; | ||
1952 | break; | ||
1953 | default: | ||
1954 | dev_err(host->dev, "Unsupported page size for NFC.\n"); | ||
1955 | res = -ENXIO; | ||
1956 | return res; | ||
1957 | } | ||
1958 | |||
1959 | /* oob bytes size = (NFCSPARESIZE + 1) * 4 | ||
1960 | * Max support spare size is 512 bytes. */ | ||
1961 | cfg_nfc |= (((mtd->oobsize / 4) - 1) << NFC_CFG_NFC_SPARESIZE_BIT_POS | ||
1962 | & NFC_CFG_NFC_SPARESIZE); | ||
1963 | /* default set a max timeout */ | ||
1964 | cfg_nfc |= NFC_CFG_RSPARE | | ||
1965 | NFC_CFG_NFC_DTOCYC | NFC_CFG_NFC_DTOMUL; | ||
1966 | |||
1967 | nfc_writel(host->nfc->hsmc_regs, CFG, cfg_nfc); | ||
1968 | |||
1969 | host->nfc->will_write_sram = false; | ||
1970 | nfc_set_sram_bank(host, 0); | ||
1971 | |||
1972 | /* Use Write page with NFC SRAM only for PMECC or ECC NONE. */ | ||
1973 | if (host->nfc->write_by_sram) { | ||
1974 | if ((chip->ecc.mode == NAND_ECC_HW && host->has_pmecc) || | ||
1975 | chip->ecc.mode == NAND_ECC_NONE) | ||
1976 | chip->write_page = nfc_sram_write_page; | ||
1977 | else | ||
1978 | host->nfc->write_by_sram = false; | ||
1979 | } | ||
1980 | |||
1981 | dev_info(host->dev, "Using NFC Sram read %s\n", | ||
1982 | host->nfc->write_by_sram ? "and write" : ""); | ||
1983 | return 0; | ||
1984 | } | ||
1985 | |||
1986 | static struct platform_driver atmel_nand_nfc_driver; | ||
1462 | /* | 1987 | /* |
1463 | * Probe for the NAND device. | 1988 | * Probe for the NAND device. |
1464 | */ | 1989 | */ |
@@ -1469,30 +1994,27 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
1469 | struct nand_chip *nand_chip; | 1994 | struct nand_chip *nand_chip; |
1470 | struct resource *mem; | 1995 | struct resource *mem; |
1471 | struct mtd_part_parser_data ppdata = {}; | 1996 | struct mtd_part_parser_data ppdata = {}; |
1472 | int res; | 1997 | int res, irq; |
1473 | struct pinctrl *pinctrl; | ||
1474 | |||
1475 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1476 | if (!mem) { | ||
1477 | printk(KERN_ERR "atmel_nand: can't get I/O resource mem\n"); | ||
1478 | return -ENXIO; | ||
1479 | } | ||
1480 | 1998 | ||
1481 | /* Allocate memory for the device structure (and zero it) */ | 1999 | /* Allocate memory for the device structure (and zero it) */ |
1482 | host = kzalloc(sizeof(struct atmel_nand_host), GFP_KERNEL); | 2000 | host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); |
1483 | if (!host) { | 2001 | if (!host) { |
1484 | printk(KERN_ERR "atmel_nand: failed to allocate device structure.\n"); | 2002 | printk(KERN_ERR "atmel_nand: failed to allocate device structure.\n"); |
1485 | return -ENOMEM; | 2003 | return -ENOMEM; |
1486 | } | 2004 | } |
1487 | 2005 | ||
1488 | host->io_phys = (dma_addr_t)mem->start; | 2006 | res = platform_driver_register(&atmel_nand_nfc_driver); |
2007 | if (res) | ||
2008 | dev_err(&pdev->dev, "atmel_nand: can't register NFC driver\n"); | ||
1489 | 2009 | ||
1490 | host->io_base = ioremap(mem->start, resource_size(mem)); | 2010 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1491 | if (host->io_base == NULL) { | 2011 | host->io_base = devm_ioremap_resource(&pdev->dev, mem); |
1492 | printk(KERN_ERR "atmel_nand: ioremap failed\n"); | 2012 | if (IS_ERR(host->io_base)) { |
1493 | res = -EIO; | 2013 | dev_err(&pdev->dev, "atmel_nand: ioremap resource failed\n"); |
2014 | res = PTR_ERR(host->io_base); | ||
1494 | goto err_nand_ioremap; | 2015 | goto err_nand_ioremap; |
1495 | } | 2016 | } |
2017 | host->io_phys = (dma_addr_t)mem->start; | ||
1496 | 2018 | ||
1497 | mtd = &host->mtd; | 2019 | mtd = &host->mtd; |
1498 | nand_chip = &host->nand_chip; | 2020 | nand_chip = &host->nand_chip; |
@@ -1500,9 +2022,9 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
1500 | if (pdev->dev.of_node) { | 2022 | if (pdev->dev.of_node) { |
1501 | res = atmel_of_init_port(host, pdev->dev.of_node); | 2023 | res = atmel_of_init_port(host, pdev->dev.of_node); |
1502 | if (res) | 2024 | if (res) |
1503 | goto err_ecc_ioremap; | 2025 | goto err_nand_ioremap; |
1504 | } else { | 2026 | } else { |
1505 | memcpy(&host->board, pdev->dev.platform_data, | 2027 | memcpy(&host->board, dev_get_platdata(&pdev->dev), |
1506 | sizeof(struct atmel_nand_data)); | 2028 | sizeof(struct atmel_nand_data)); |
1507 | } | 2029 | } |
1508 | 2030 | ||
@@ -1513,51 +2035,36 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
1513 | /* Set address of NAND IO lines */ | 2035 | /* Set address of NAND IO lines */ |
1514 | nand_chip->IO_ADDR_R = host->io_base; | 2036 | nand_chip->IO_ADDR_R = host->io_base; |
1515 | nand_chip->IO_ADDR_W = host->io_base; | 2037 | nand_chip->IO_ADDR_W = host->io_base; |
1516 | nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl; | ||
1517 | 2038 | ||
1518 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | 2039 | if (nand_nfc.is_initialized) { |
1519 | if (IS_ERR(pinctrl)) { | 2040 | /* NFC driver is probed and initialized */ |
1520 | dev_err(host->dev, "Failed to request pinctrl\n"); | 2041 | host->nfc = &nand_nfc; |
1521 | res = PTR_ERR(pinctrl); | ||
1522 | goto err_ecc_ioremap; | ||
1523 | } | ||
1524 | 2042 | ||
1525 | if (gpio_is_valid(host->board.rdy_pin)) { | 2043 | nand_chip->select_chip = nfc_select_chip; |
1526 | res = gpio_request(host->board.rdy_pin, "nand_rdy"); | 2044 | nand_chip->dev_ready = nfc_device_ready; |
1527 | if (res < 0) { | 2045 | nand_chip->cmdfunc = nfc_nand_command; |
1528 | dev_err(&pdev->dev, | ||
1529 | "can't request rdy gpio %d\n", | ||
1530 | host->board.rdy_pin); | ||
1531 | goto err_ecc_ioremap; | ||
1532 | } | ||
1533 | 2046 | ||
1534 | res = gpio_direction_input(host->board.rdy_pin); | 2047 | /* Initialize the interrupt for NFC */ |
1535 | if (res < 0) { | 2048 | irq = platform_get_irq(pdev, 0); |
1536 | dev_err(&pdev->dev, | 2049 | if (irq < 0) { |
1537 | "can't request input direction rdy gpio %d\n", | 2050 | dev_err(host->dev, "Cannot get HSMC irq!\n"); |
1538 | host->board.rdy_pin); | 2051 | res = irq; |
1539 | goto err_ecc_ioremap; | 2052 | goto err_nand_ioremap; |
1540 | } | 2053 | } |
1541 | 2054 | ||
1542 | nand_chip->dev_ready = atmel_nand_device_ready; | 2055 | res = devm_request_irq(&pdev->dev, irq, hsmc_interrupt, |
1543 | } | 2056 | 0, "hsmc", host); |
1544 | 2057 | if (res) { | |
1545 | if (gpio_is_valid(host->board.enable_pin)) { | 2058 | dev_err(&pdev->dev, "Unable to request HSMC irq %d\n", |
1546 | res = gpio_request(host->board.enable_pin, "nand_enable"); | 2059 | irq); |
1547 | if (res < 0) { | 2060 | goto err_nand_ioremap; |
1548 | dev_err(&pdev->dev, | ||
1549 | "can't request enable gpio %d\n", | ||
1550 | host->board.enable_pin); | ||
1551 | goto err_ecc_ioremap; | ||
1552 | } | 2061 | } |
2062 | } else { | ||
2063 | res = atmel_nand_set_enable_ready_pins(mtd); | ||
2064 | if (res) | ||
2065 | goto err_nand_ioremap; | ||
1553 | 2066 | ||
1554 | res = gpio_direction_output(host->board.enable_pin, 1); | 2067 | nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl; |
1555 | if (res < 0) { | ||
1556 | dev_err(&pdev->dev, | ||
1557 | "can't request output direction enable gpio %d\n", | ||
1558 | host->board.enable_pin); | ||
1559 | goto err_ecc_ioremap; | ||
1560 | } | ||
1561 | } | 2068 | } |
1562 | 2069 | ||
1563 | nand_chip->ecc.mode = host->board.ecc_mode; | 2070 | nand_chip->ecc.mode = host->board.ecc_mode; |
@@ -1573,7 +2080,8 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
1573 | atmel_nand_enable(host); | 2080 | atmel_nand_enable(host); |
1574 | 2081 | ||
1575 | if (gpio_is_valid(host->board.det_pin)) { | 2082 | if (gpio_is_valid(host->board.det_pin)) { |
1576 | res = gpio_request(host->board.det_pin, "nand_det"); | 2083 | res = devm_gpio_request(&pdev->dev, |
2084 | host->board.det_pin, "nand_det"); | ||
1577 | if (res < 0) { | 2085 | if (res < 0) { |
1578 | dev_err(&pdev->dev, | 2086 | dev_err(&pdev->dev, |
1579 | "can't request det gpio %d\n", | 2087 | "can't request det gpio %d\n", |
@@ -1601,7 +2109,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
1601 | nand_chip->bbt_options |= NAND_BBT_USE_FLASH; | 2109 | nand_chip->bbt_options |= NAND_BBT_USE_FLASH; |
1602 | } | 2110 | } |
1603 | 2111 | ||
1604 | if (!cpu_has_dma()) | 2112 | if (!host->board.has_dma) |
1605 | use_dma = 0; | 2113 | use_dma = 0; |
1606 | 2114 | ||
1607 | if (use_dma) { | 2115 | if (use_dma) { |
@@ -1637,6 +2145,15 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
1637 | goto err_hw_ecc; | 2145 | goto err_hw_ecc; |
1638 | } | 2146 | } |
1639 | 2147 | ||
2148 | /* initialize the nfc configuration register */ | ||
2149 | if (host->nfc && host->nfc->use_nfc_sram) { | ||
2150 | res = nfc_sram_init(mtd); | ||
2151 | if (res) { | ||
2152 | host->nfc->use_nfc_sram = false; | ||
2153 | dev_err(host->dev, "Disable use nfc sram for data transfer.\n"); | ||
2154 | } | ||
2155 | } | ||
2156 | |||
1640 | /* second phase scan */ | 2157 | /* second phase scan */ |
1641 | if (nand_scan_tail(mtd)) { | 2158 | if (nand_scan_tail(mtd)) { |
1642 | res = -ENXIO; | 2159 | res = -ENXIO; |
@@ -1651,27 +2168,16 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
1651 | return res; | 2168 | return res; |
1652 | 2169 | ||
1653 | err_scan_tail: | 2170 | err_scan_tail: |
1654 | if (host->has_pmecc && host->nand_chip.ecc.mode == NAND_ECC_HW) { | 2171 | if (host->has_pmecc && host->nand_chip.ecc.mode == NAND_ECC_HW) |
1655 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); | 2172 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); |
1656 | pmecc_data_free(host); | ||
1657 | } | ||
1658 | if (host->ecc) | ||
1659 | iounmap(host->ecc); | ||
1660 | if (host->pmerrloc_base) | ||
1661 | iounmap(host->pmerrloc_base); | ||
1662 | if (host->pmecc_rom_base) | ||
1663 | iounmap(host->pmecc_rom_base); | ||
1664 | err_hw_ecc: | 2173 | err_hw_ecc: |
1665 | err_scan_ident: | 2174 | err_scan_ident: |
1666 | err_no_card: | 2175 | err_no_card: |
1667 | atmel_nand_disable(host); | 2176 | atmel_nand_disable(host); |
1668 | platform_set_drvdata(pdev, NULL); | ||
1669 | if (host->dma_chan) | 2177 | if (host->dma_chan) |
1670 | dma_release_channel(host->dma_chan); | 2178 | dma_release_channel(host->dma_chan); |
1671 | err_ecc_ioremap: | ||
1672 | iounmap(host->io_base); | ||
1673 | err_nand_ioremap: | 2179 | err_nand_ioremap: |
1674 | kfree(host); | 2180 | platform_driver_unregister(&atmel_nand_nfc_driver); |
1675 | return res; | 2181 | return res; |
1676 | } | 2182 | } |
1677 | 2183 | ||
@@ -1691,30 +2197,12 @@ static int __exit atmel_nand_remove(struct platform_device *pdev) | |||
1691 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); | 2197 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); |
1692 | pmerrloc_writel(host->pmerrloc_base, ELDIS, | 2198 | pmerrloc_writel(host->pmerrloc_base, ELDIS, |
1693 | PMERRLOC_DISABLE); | 2199 | PMERRLOC_DISABLE); |
1694 | pmecc_data_free(host); | ||
1695 | } | 2200 | } |
1696 | 2201 | ||
1697 | if (gpio_is_valid(host->board.det_pin)) | ||
1698 | gpio_free(host->board.det_pin); | ||
1699 | |||
1700 | if (gpio_is_valid(host->board.enable_pin)) | ||
1701 | gpio_free(host->board.enable_pin); | ||
1702 | |||
1703 | if (gpio_is_valid(host->board.rdy_pin)) | ||
1704 | gpio_free(host->board.rdy_pin); | ||
1705 | |||
1706 | if (host->ecc) | ||
1707 | iounmap(host->ecc); | ||
1708 | if (host->pmecc_rom_base) | ||
1709 | iounmap(host->pmecc_rom_base); | ||
1710 | if (host->pmerrloc_base) | ||
1711 | iounmap(host->pmerrloc_base); | ||
1712 | |||
1713 | if (host->dma_chan) | 2202 | if (host->dma_chan) |
1714 | dma_release_channel(host->dma_chan); | 2203 | dma_release_channel(host->dma_chan); |
1715 | 2204 | ||
1716 | iounmap(host->io_base); | 2205 | platform_driver_unregister(&atmel_nand_nfc_driver); |
1717 | kfree(host); | ||
1718 | 2206 | ||
1719 | return 0; | 2207 | return 0; |
1720 | } | 2208 | } |
@@ -1728,6 +2216,59 @@ static const struct of_device_id atmel_nand_dt_ids[] = { | |||
1728 | MODULE_DEVICE_TABLE(of, atmel_nand_dt_ids); | 2216 | MODULE_DEVICE_TABLE(of, atmel_nand_dt_ids); |
1729 | #endif | 2217 | #endif |
1730 | 2218 | ||
2219 | static int atmel_nand_nfc_probe(struct platform_device *pdev) | ||
2220 | { | ||
2221 | struct atmel_nfc *nfc = &nand_nfc; | ||
2222 | struct resource *nfc_cmd_regs, *nfc_hsmc_regs, *nfc_sram; | ||
2223 | |||
2224 | nfc_cmd_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
2225 | nfc->base_cmd_regs = devm_ioremap_resource(&pdev->dev, nfc_cmd_regs); | ||
2226 | if (IS_ERR(nfc->base_cmd_regs)) | ||
2227 | return PTR_ERR(nfc->base_cmd_regs); | ||
2228 | |||
2229 | nfc_hsmc_regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
2230 | nfc->hsmc_regs = devm_ioremap_resource(&pdev->dev, nfc_hsmc_regs); | ||
2231 | if (IS_ERR(nfc->hsmc_regs)) | ||
2232 | return PTR_ERR(nfc->hsmc_regs); | ||
2233 | |||
2234 | nfc_sram = platform_get_resource(pdev, IORESOURCE_MEM, 2); | ||
2235 | if (nfc_sram) { | ||
2236 | nfc->sram_bank0 = devm_ioremap_resource(&pdev->dev, nfc_sram); | ||
2237 | if (IS_ERR(nfc->sram_bank0)) { | ||
2238 | dev_warn(&pdev->dev, "Fail to ioremap the NFC sram with error: %ld. So disable NFC sram.\n", | ||
2239 | PTR_ERR(nfc->sram_bank0)); | ||
2240 | } else { | ||
2241 | nfc->use_nfc_sram = true; | ||
2242 | nfc->sram_bank0_phys = (dma_addr_t)nfc_sram->start; | ||
2243 | |||
2244 | if (pdev->dev.of_node) | ||
2245 | nfc->write_by_sram = of_property_read_bool( | ||
2246 | pdev->dev.of_node, | ||
2247 | "atmel,write-by-sram"); | ||
2248 | } | ||
2249 | } | ||
2250 | |||
2251 | nfc->is_initialized = true; | ||
2252 | dev_info(&pdev->dev, "NFC is probed.\n"); | ||
2253 | return 0; | ||
2254 | } | ||
2255 | |||
2256 | #if defined(CONFIG_OF) | ||
2257 | static struct of_device_id atmel_nand_nfc_match[] = { | ||
2258 | { .compatible = "atmel,sama5d3-nfc" }, | ||
2259 | { /* sentinel */ } | ||
2260 | }; | ||
2261 | #endif | ||
2262 | |||
2263 | static struct platform_driver atmel_nand_nfc_driver = { | ||
2264 | .driver = { | ||
2265 | .name = "atmel_nand_nfc", | ||
2266 | .owner = THIS_MODULE, | ||
2267 | .of_match_table = of_match_ptr(atmel_nand_nfc_match), | ||
2268 | }, | ||
2269 | .probe = atmel_nand_nfc_probe, | ||
2270 | }; | ||
2271 | |||
1731 | static struct platform_driver atmel_nand_driver = { | 2272 | static struct platform_driver atmel_nand_driver = { |
1732 | .remove = __exit_p(atmel_nand_remove), | 2273 | .remove = __exit_p(atmel_nand_remove), |
1733 | .driver = { | 2274 | .driver = { |
diff --git a/drivers/mtd/nand/atmel_nand_nfc.h b/drivers/mtd/nand/atmel_nand_nfc.h new file mode 100644 index 000000000000..4efd117cd3a3 --- /dev/null +++ b/drivers/mtd/nand/atmel_nand_nfc.h | |||
@@ -0,0 +1,98 @@ | |||
1 | /* | ||
2 | * Atmel Nand Flash Controller (NFC) - System peripherals regsters. | ||
3 | * Based on SAMA5D3 datasheet. | ||
4 | * | ||
5 | * © Copyright 2013 Atmel Corporation. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #ifndef ATMEL_NAND_NFC_H | ||
14 | #define ATMEL_NAND_NFC_H | ||
15 | |||
16 | /* | ||
17 | * HSMC NFC registers | ||
18 | */ | ||
19 | #define ATMEL_HSMC_NFC_CFG 0x00 /* NFC Configuration Register */ | ||
20 | #define NFC_CFG_PAGESIZE (7 << 0) | ||
21 | #define NFC_CFG_PAGESIZE_512 (0 << 0) | ||
22 | #define NFC_CFG_PAGESIZE_1024 (1 << 0) | ||
23 | #define NFC_CFG_PAGESIZE_2048 (2 << 0) | ||
24 | #define NFC_CFG_PAGESIZE_4096 (3 << 0) | ||
25 | #define NFC_CFG_PAGESIZE_8192 (4 << 0) | ||
26 | #define NFC_CFG_WSPARE (1 << 8) | ||
27 | #define NFC_CFG_RSPARE (1 << 9) | ||
28 | #define NFC_CFG_NFC_DTOCYC (0xf << 16) | ||
29 | #define NFC_CFG_NFC_DTOMUL (0x7 << 20) | ||
30 | #define NFC_CFG_NFC_SPARESIZE (0x7f << 24) | ||
31 | #define NFC_CFG_NFC_SPARESIZE_BIT_POS 24 | ||
32 | |||
33 | #define ATMEL_HSMC_NFC_CTRL 0x04 /* NFC Control Register */ | ||
34 | #define NFC_CTRL_ENABLE (1 << 0) | ||
35 | #define NFC_CTRL_DISABLE (1 << 1) | ||
36 | |||
37 | #define ATMEL_HSMC_NFC_SR 0x08 /* NFC Status Register */ | ||
38 | #define NFC_SR_XFR_DONE (1 << 16) | ||
39 | #define NFC_SR_CMD_DONE (1 << 17) | ||
40 | #define NFC_SR_RB_EDGE (1 << 24) | ||
41 | |||
42 | #define ATMEL_HSMC_NFC_IER 0x0c | ||
43 | #define ATMEL_HSMC_NFC_IDR 0x10 | ||
44 | #define ATMEL_HSMC_NFC_IMR 0x14 | ||
45 | #define ATMEL_HSMC_NFC_CYCLE0 0x18 /* NFC Address Cycle Zero */ | ||
46 | #define ATMEL_HSMC_NFC_ADDR_CYCLE0 (0xff) | ||
47 | |||
48 | #define ATMEL_HSMC_NFC_BANK 0x1c /* NFC Bank Register */ | ||
49 | #define ATMEL_HSMC_NFC_BANK0 (0 << 0) | ||
50 | #define ATMEL_HSMC_NFC_BANK1 (1 << 0) | ||
51 | |||
52 | #define nfc_writel(addr, reg, value) \ | ||
53 | writel((value), (addr) + ATMEL_HSMC_NFC_##reg) | ||
54 | |||
55 | #define nfc_readl(addr, reg) \ | ||
56 | readl_relaxed((addr) + ATMEL_HSMC_NFC_##reg) | ||
57 | |||
58 | /* | ||
59 | * NFC Address Command definitions | ||
60 | */ | ||
61 | #define NFCADDR_CMD_CMD1 (0xff << 2) /* Command for Cycle 1 */ | ||
62 | #define NFCADDR_CMD_CMD1_BIT_POS 2 | ||
63 | #define NFCADDR_CMD_CMD2 (0xff << 10) /* Command for Cycle 2 */ | ||
64 | #define NFCADDR_CMD_CMD2_BIT_POS 10 | ||
65 | #define NFCADDR_CMD_VCMD2 (0x1 << 18) /* Valid Cycle 2 Command */ | ||
66 | #define NFCADDR_CMD_ACYCLE (0x7 << 19) /* Number of Address required */ | ||
67 | #define NFCADDR_CMD_ACYCLE_NONE (0x0 << 19) | ||
68 | #define NFCADDR_CMD_ACYCLE_1 (0x1 << 19) | ||
69 | #define NFCADDR_CMD_ACYCLE_2 (0x2 << 19) | ||
70 | #define NFCADDR_CMD_ACYCLE_3 (0x3 << 19) | ||
71 | #define NFCADDR_CMD_ACYCLE_4 (0x4 << 19) | ||
72 | #define NFCADDR_CMD_ACYCLE_5 (0x5 << 19) | ||
73 | #define NFCADDR_CMD_ACYCLE_BIT_POS 19 | ||
74 | #define NFCADDR_CMD_CSID (0x7 << 22) /* Chip Select Identifier */ | ||
75 | #define NFCADDR_CMD_CSID_0 (0x0 << 22) | ||
76 | #define NFCADDR_CMD_CSID_1 (0x1 << 22) | ||
77 | #define NFCADDR_CMD_CSID_2 (0x2 << 22) | ||
78 | #define NFCADDR_CMD_CSID_3 (0x3 << 22) | ||
79 | #define NFCADDR_CMD_CSID_4 (0x4 << 22) | ||
80 | #define NFCADDR_CMD_CSID_5 (0x5 << 22) | ||
81 | #define NFCADDR_CMD_CSID_6 (0x6 << 22) | ||
82 | #define NFCADDR_CMD_CSID_7 (0x7 << 22) | ||
83 | #define NFCADDR_CMD_DATAEN (0x1 << 25) /* Data Transfer Enable */ | ||
84 | #define NFCADDR_CMD_DATADIS (0x0 << 25) /* Data Transfer Disable */ | ||
85 | #define NFCADDR_CMD_NFCRD (0x0 << 26) /* NFC Read Enable */ | ||
86 | #define NFCADDR_CMD_NFCWR (0x1 << 26) /* NFC Write Enable */ | ||
87 | #define NFCADDR_CMD_NFCBUSY (0x1 << 27) /* NFC Busy */ | ||
88 | |||
89 | #define nfc_cmd_addr1234_writel(cmd, addr1234, nfc_base) \ | ||
90 | writel((addr1234), (cmd) + nfc_base) | ||
91 | |||
92 | #define nfc_cmd_readl(bitstatus, nfc_base) \ | ||
93 | readl_relaxed((bitstatus) + nfc_base) | ||
94 | |||
95 | #define NFC_TIME_OUT_MS 100 | ||
96 | #define NFC_SRAM_BANK1_OFFSET 0x1200 | ||
97 | |||
98 | #endif | ||
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 217459d02b2f..ae8dd7c41039 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c | |||
@@ -411,7 +411,7 @@ static int au1550nd_probe(struct platform_device *pdev) | |||
411 | struct resource *r; | 411 | struct resource *r; |
412 | int ret, cs; | 412 | int ret, cs; |
413 | 413 | ||
414 | pd = pdev->dev.platform_data; | 414 | pd = dev_get_platdata(&pdev->dev); |
415 | if (!pd) { | 415 | if (!pd) { |
416 | dev_err(&pdev->dev, "missing platform data\n"); | 416 | dev_err(&pdev->dev, "missing platform data\n"); |
417 | return -ENODEV; | 417 | return -ENODEV; |
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 776df3694f75..2c42e125720f 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c | |||
@@ -171,7 +171,7 @@ static struct bf5xx_nand_info *to_nand_info(struct platform_device *pdev) | |||
171 | 171 | ||
172 | static struct bf5xx_nand_platform *to_nand_plat(struct platform_device *pdev) | 172 | static struct bf5xx_nand_platform *to_nand_plat(struct platform_device *pdev) |
173 | { | 173 | { |
174 | return pdev->dev.platform_data; | 174 | return dev_get_platdata(&pdev->dev); |
175 | } | 175 | } |
176 | 176 | ||
177 | /* | 177 | /* |
@@ -671,8 +671,6 @@ static int bf5xx_nand_remove(struct platform_device *pdev) | |||
671 | { | 671 | { |
672 | struct bf5xx_nand_info *info = to_nand_info(pdev); | 672 | struct bf5xx_nand_info *info = to_nand_info(pdev); |
673 | 673 | ||
674 | platform_set_drvdata(pdev, NULL); | ||
675 | |||
676 | /* first thing we need to do is release all our mtds | 674 | /* first thing we need to do is release all our mtds |
677 | * and their partitions, then go through freeing the | 675 | * and their partitions, then go through freeing the |
678 | * resources used | 676 | * resources used |
@@ -832,7 +830,6 @@ static int bf5xx_nand_probe(struct platform_device *pdev) | |||
832 | out_err_nand_scan: | 830 | out_err_nand_scan: |
833 | bf5xx_nand_dma_remove(info); | 831 | bf5xx_nand_dma_remove(info); |
834 | out_err_hw_init: | 832 | out_err_hw_init: |
835 | platform_set_drvdata(pdev, NULL); | ||
836 | kfree(info); | 833 | kfree(info); |
837 | out_err_kzalloc: | 834 | out_err_kzalloc: |
838 | peripheral_free_list(bfin_nfc_pin_req); | 835 | peripheral_free_list(bfin_nfc_pin_req); |
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c index 2cdeab8bebc4..d469a9a1dea0 100644 --- a/drivers/mtd/nand/cs553x_nand.c +++ b/drivers/mtd/nand/cs553x_nand.c | |||
@@ -197,7 +197,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) | |||
197 | } | 197 | } |
198 | 198 | ||
199 | /* Allocate memory for MTD device structure and private data */ | 199 | /* Allocate memory for MTD device structure and private data */ |
200 | new_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); | 200 | new_mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); |
201 | if (!new_mtd) { | 201 | if (!new_mtd) { |
202 | printk(KERN_WARNING "Unable to allocate CS553X NAND MTD device structure.\n"); | 202 | printk(KERN_WARNING "Unable to allocate CS553X NAND MTD device structure.\n"); |
203 | err = -ENOMEM; | 203 | err = -ENOMEM; |
@@ -207,10 +207,6 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) | |||
207 | /* Get pointer to private data */ | 207 | /* Get pointer to private data */ |
208 | this = (struct nand_chip *)(&new_mtd[1]); | 208 | this = (struct nand_chip *)(&new_mtd[1]); |
209 | 209 | ||
210 | /* Initialize structures */ | ||
211 | memset(new_mtd, 0, sizeof(struct mtd_info)); | ||
212 | memset(this, 0, sizeof(struct nand_chip)); | ||
213 | |||
214 | /* Link the private data with the MTD structure */ | 210 | /* Link the private data with the MTD structure */ |
215 | new_mtd->priv = this; | 211 | new_mtd->priv = this; |
216 | new_mtd->owner = THIS_MODULE; | 212 | new_mtd->owner = THIS_MODULE; |
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index c3e15a558173..b77a01efb483 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c | |||
@@ -530,7 +530,7 @@ MODULE_DEVICE_TABLE(of, davinci_nand_of_match); | |||
530 | static struct davinci_nand_pdata | 530 | static struct davinci_nand_pdata |
531 | *nand_davinci_get_pdata(struct platform_device *pdev) | 531 | *nand_davinci_get_pdata(struct platform_device *pdev) |
532 | { | 532 | { |
533 | if (!pdev->dev.platform_data && pdev->dev.of_node) { | 533 | if (!dev_get_platdata(&pdev->dev) && pdev->dev.of_node) { |
534 | struct davinci_nand_pdata *pdata; | 534 | struct davinci_nand_pdata *pdata; |
535 | const char *mode; | 535 | const char *mode; |
536 | u32 prop; | 536 | u32 prop; |
@@ -575,13 +575,13 @@ static struct davinci_nand_pdata | |||
575 | pdata->bbt_options = NAND_BBT_USE_FLASH; | 575 | pdata->bbt_options = NAND_BBT_USE_FLASH; |
576 | } | 576 | } |
577 | 577 | ||
578 | return pdev->dev.platform_data; | 578 | return dev_get_platdata(&pdev->dev); |
579 | } | 579 | } |
580 | #else | 580 | #else |
581 | static struct davinci_nand_pdata | 581 | static struct davinci_nand_pdata |
582 | *nand_davinci_get_pdata(struct platform_device *pdev) | 582 | *nand_davinci_get_pdata(struct platform_device *pdev) |
583 | { | 583 | { |
584 | return pdev->dev.platform_data; | 584 | return dev_get_platdata(&pdev->dev); |
585 | } | 585 | } |
586 | #endif | 586 | #endif |
587 | 587 | ||
@@ -623,11 +623,14 @@ static int __init nand_davinci_probe(struct platform_device *pdev) | |||
623 | goto err_nomem; | 623 | goto err_nomem; |
624 | } | 624 | } |
625 | 625 | ||
626 | vaddr = devm_request_and_ioremap(&pdev->dev, res1); | 626 | vaddr = devm_ioremap_resource(&pdev->dev, res1); |
627 | base = devm_request_and_ioremap(&pdev->dev, res2); | 627 | if (IS_ERR(vaddr)) { |
628 | if (!vaddr || !base) { | 628 | ret = PTR_ERR(vaddr); |
629 | dev_err(&pdev->dev, "ioremap failed\n"); | 629 | goto err_ioremap; |
630 | ret = -EADDRNOTAVAIL; | 630 | } |
631 | base = devm_ioremap_resource(&pdev->dev, res2); | ||
632 | if (IS_ERR(base)) { | ||
633 | ret = PTR_ERR(base); | ||
631 | goto err_ioremap; | 634 | goto err_ioremap; |
632 | } | 635 | } |
633 | 636 | ||
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 0c8bb6bf8424..2ed2bb33a6e7 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c | |||
@@ -1520,7 +1520,7 @@ int denali_init(struct denali_nand_info *denali) | |||
1520 | * so just let controller do 15bit ECC for MLC and 8bit ECC for | 1520 | * so just let controller do 15bit ECC for MLC and 8bit ECC for |
1521 | * SLC if possible. | 1521 | * SLC if possible. |
1522 | * */ | 1522 | * */ |
1523 | if (denali->nand.cellinfo & 0xc && | 1523 | if (denali->nand.cellinfo & NAND_CI_CELLTYPE_MSK && |
1524 | (denali->mtd.oobsize > (denali->bbtskipbytes + | 1524 | (denali->mtd.oobsize > (denali->bbtskipbytes + |
1525 | ECC_15BITS * (denali->mtd.writesize / | 1525 | ECC_15BITS * (denali->mtd.writesize / |
1526 | ECC_SECTOR_SIZE)))) { | 1526 | ECC_SECTOR_SIZE)))) { |
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 81fa5784f98b..eaa3c29ad860 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c | |||
@@ -46,13 +46,13 @@ static unsigned long __initdata doc_locations[] = { | |||
46 | 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, | 46 | 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, |
47 | 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000, | 47 | 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000, |
48 | 0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000, | 48 | 0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000, |
49 | #else /* CONFIG_MTD_DOCPROBE_HIGH */ | 49 | #else |
50 | 0xc8000, 0xca000, 0xcc000, 0xce000, | 50 | 0xc8000, 0xca000, 0xcc000, 0xce000, |
51 | 0xd0000, 0xd2000, 0xd4000, 0xd6000, | 51 | 0xd0000, 0xd2000, 0xd4000, 0xd6000, |
52 | 0xd8000, 0xda000, 0xdc000, 0xde000, | 52 | 0xd8000, 0xda000, 0xdc000, 0xde000, |
53 | 0xe0000, 0xe2000, 0xe4000, 0xe6000, | 53 | 0xe0000, 0xe2000, 0xe4000, 0xe6000, |
54 | 0xe8000, 0xea000, 0xec000, 0xee000, | 54 | 0xe8000, 0xea000, 0xec000, 0xee000, |
55 | #endif /* CONFIG_MTD_DOCPROBE_HIGH */ | 55 | #endif |
56 | #endif | 56 | #endif |
57 | 0xffffffff }; | 57 | 0xffffffff }; |
58 | 58 | ||
diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c index fa25e7a08134..548db2389fab 100644 --- a/drivers/mtd/nand/docg4.c +++ b/drivers/mtd/nand/docg4.c | |||
@@ -1093,7 +1093,6 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
1093 | struct nand_chip *nand = mtd->priv; | 1093 | struct nand_chip *nand = mtd->priv; |
1094 | struct docg4_priv *doc = nand->priv; | 1094 | struct docg4_priv *doc = nand->priv; |
1095 | struct nand_bbt_descr *bbtd = nand->badblock_pattern; | 1095 | struct nand_bbt_descr *bbtd = nand->badblock_pattern; |
1096 | int block = (int)(ofs >> nand->bbt_erase_shift); | ||
1097 | int page = (int)(ofs >> nand->page_shift); | 1096 | int page = (int)(ofs >> nand->page_shift); |
1098 | uint32_t g4_addr = mtd_to_docg4_address(page, 0); | 1097 | uint32_t g4_addr = mtd_to_docg4_address(page, 0); |
1099 | 1098 | ||
@@ -1108,9 +1107,6 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
1108 | if (buf == NULL) | 1107 | if (buf == NULL) |
1109 | return -ENOMEM; | 1108 | return -ENOMEM; |
1110 | 1109 | ||
1111 | /* update bbt in memory */ | ||
1112 | nand->bbt[block / 4] |= 0x01 << ((block & 0x03) * 2); | ||
1113 | |||
1114 | /* write bit-wise negation of pattern to oob buffer */ | 1110 | /* write bit-wise negation of pattern to oob buffer */ |
1115 | memset(nand->oob_poi, 0xff, mtd->oobsize); | 1111 | memset(nand->oob_poi, 0xff, mtd->oobsize); |
1116 | for (i = 0; i < bbtd->len; i++) | 1112 | for (i = 0; i < bbtd->len; i++) |
@@ -1120,8 +1116,6 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
1120 | write_page_prologue(mtd, g4_addr); | 1116 | write_page_prologue(mtd, g4_addr); |
1121 | docg4_write_page(mtd, nand, buf, 1); | 1117 | docg4_write_page(mtd, nand, buf, 1); |
1122 | ret = pageprog(mtd); | 1118 | ret = pageprog(mtd); |
1123 | if (!ret) | ||
1124 | mtd->ecc_stats.badblocks++; | ||
1125 | 1119 | ||
1126 | kfree(buf); | 1120 | kfree(buf); |
1127 | 1121 | ||
@@ -1368,7 +1362,6 @@ static int __init probe_docg4(struct platform_device *pdev) | |||
1368 | struct nand_chip *nand = mtd->priv; | 1362 | struct nand_chip *nand = mtd->priv; |
1369 | struct docg4_priv *doc = nand->priv; | 1363 | struct docg4_priv *doc = nand->priv; |
1370 | nand_release(mtd); /* deletes partitions and mtd devices */ | 1364 | nand_release(mtd); /* deletes partitions and mtd devices */ |
1371 | platform_set_drvdata(pdev, NULL); | ||
1372 | free_bch(doc->bch); | 1365 | free_bch(doc->bch); |
1373 | kfree(mtd); | 1366 | kfree(mtd); |
1374 | } | 1367 | } |
@@ -1380,7 +1373,6 @@ static int __exit cleanup_docg4(struct platform_device *pdev) | |||
1380 | { | 1373 | { |
1381 | struct docg4_priv *doc = platform_get_drvdata(pdev); | 1374 | struct docg4_priv *doc = platform_get_drvdata(pdev); |
1382 | nand_release(doc->mtd); | 1375 | nand_release(doc->mtd); |
1383 | platform_set_drvdata(pdev, NULL); | ||
1384 | free_bch(doc->bch); | 1376 | free_bch(doc->bch); |
1385 | kfree(doc->mtd); | 1377 | kfree(doc->mtd); |
1386 | iounmap(doc->virtadr); | 1378 | iounmap(doc->virtadr); |
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index f1f7f12ab501..317a771f1587 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c | |||
@@ -823,7 +823,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) | |||
823 | 823 | ||
824 | /* set up nand options */ | 824 | /* set up nand options */ |
825 | chip->bbt_options = NAND_BBT_USE_FLASH; | 825 | chip->bbt_options = NAND_BBT_USE_FLASH; |
826 | 826 | chip->options = NAND_NO_SUBPAGE_WRITE; | |
827 | 827 | ||
828 | if (ioread32be(&ifc->cspr_cs[priv->bank].cspr) & CSPR_PORT_SIZE_16) { | 828 | if (ioread32be(&ifc->cspr_cs[priv->bank].cspr) & CSPR_PORT_SIZE_16) { |
829 | chip->read_byte = fsl_ifc_read_byte16; | 829 | chip->read_byte = fsl_ifc_read_byte16; |
@@ -908,7 +908,6 @@ static int fsl_ifc_chip_remove(struct fsl_ifc_mtd *priv) | |||
908 | 908 | ||
909 | ifc_nand_ctrl->chips[priv->bank] = NULL; | 909 | ifc_nand_ctrl->chips[priv->bank] = NULL; |
910 | dev_set_drvdata(priv->dev, NULL); | 910 | dev_set_drvdata(priv->dev, NULL); |
911 | kfree(priv); | ||
912 | 911 | ||
913 | return 0; | 912 | return 0; |
914 | } | 913 | } |
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index 911e2433fe30..3dc1a7564d87 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c | |||
@@ -889,6 +889,24 @@ static int fsmc_nand_probe_config_dt(struct platform_device *pdev, | |||
889 | if (of_get_property(np, "nand-skip-bbtscan", NULL)) | 889 | if (of_get_property(np, "nand-skip-bbtscan", NULL)) |
890 | pdata->options = NAND_SKIP_BBTSCAN; | 890 | pdata->options = NAND_SKIP_BBTSCAN; |
891 | 891 | ||
892 | pdata->nand_timings = devm_kzalloc(&pdev->dev, | ||
893 | sizeof(*pdata->nand_timings), GFP_KERNEL); | ||
894 | if (!pdata->nand_timings) { | ||
895 | dev_err(&pdev->dev, "no memory for nand_timing\n"); | ||
896 | return -ENOMEM; | ||
897 | } | ||
898 | of_property_read_u8_array(np, "timings", (u8 *)pdata->nand_timings, | ||
899 | sizeof(*pdata->nand_timings)); | ||
900 | |||
901 | /* Set default NAND bank to 0 */ | ||
902 | pdata->bank = 0; | ||
903 | if (!of_property_read_u32(np, "bank", &val)) { | ||
904 | if (val > 3) { | ||
905 | dev_err(&pdev->dev, "invalid bank %u\n", val); | ||
906 | return -EINVAL; | ||
907 | } | ||
908 | pdata->bank = val; | ||
909 | } | ||
892 | return 0; | 910 | return 0; |
893 | } | 911 | } |
894 | #else | 912 | #else |
@@ -940,9 +958,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) | |||
940 | } | 958 | } |
941 | 959 | ||
942 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_data"); | 960 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_data"); |
943 | if (!res) | ||
944 | return -EINVAL; | ||
945 | |||
946 | host->data_va = devm_ioremap_resource(&pdev->dev, res); | 961 | host->data_va = devm_ioremap_resource(&pdev->dev, res); |
947 | if (IS_ERR(host->data_va)) | 962 | if (IS_ERR(host->data_va)) |
948 | return PTR_ERR(host->data_va); | 963 | return PTR_ERR(host->data_va); |
@@ -950,25 +965,16 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) | |||
950 | host->data_pa = (dma_addr_t)res->start; | 965 | host->data_pa = (dma_addr_t)res->start; |
951 | 966 | ||
952 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_addr"); | 967 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_addr"); |
953 | if (!res) | ||
954 | return -EINVAL; | ||
955 | |||
956 | host->addr_va = devm_ioremap_resource(&pdev->dev, res); | 968 | host->addr_va = devm_ioremap_resource(&pdev->dev, res); |
957 | if (IS_ERR(host->addr_va)) | 969 | if (IS_ERR(host->addr_va)) |
958 | return PTR_ERR(host->addr_va); | 970 | return PTR_ERR(host->addr_va); |
959 | 971 | ||
960 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_cmd"); | 972 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_cmd"); |
961 | if (!res) | ||
962 | return -EINVAL; | ||
963 | |||
964 | host->cmd_va = devm_ioremap_resource(&pdev->dev, res); | 973 | host->cmd_va = devm_ioremap_resource(&pdev->dev, res); |
965 | if (IS_ERR(host->cmd_va)) | 974 | if (IS_ERR(host->cmd_va)) |
966 | return PTR_ERR(host->cmd_va); | 975 | return PTR_ERR(host->cmd_va); |
967 | 976 | ||
968 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fsmc_regs"); | 977 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fsmc_regs"); |
969 | if (!res) | ||
970 | return -EINVAL; | ||
971 | |||
972 | host->regs_va = devm_ioremap_resource(&pdev->dev, res); | 978 | host->regs_va = devm_ioremap_resource(&pdev->dev, res); |
973 | if (IS_ERR(host->regs_va)) | 979 | if (IS_ERR(host->regs_va)) |
974 | return PTR_ERR(host->regs_va); | 980 | return PTR_ERR(host->regs_va); |
@@ -1174,8 +1180,6 @@ static int fsmc_nand_remove(struct platform_device *pdev) | |||
1174 | { | 1180 | { |
1175 | struct fsmc_nand_data *host = platform_get_drvdata(pdev); | 1181 | struct fsmc_nand_data *host = platform_get_drvdata(pdev); |
1176 | 1182 | ||
1177 | platform_set_drvdata(pdev, NULL); | ||
1178 | |||
1179 | if (host) { | 1183 | if (host) { |
1180 | nand_release(&host->mtd); | 1184 | nand_release(&host->mtd); |
1181 | 1185 | ||
@@ -1190,7 +1194,7 @@ static int fsmc_nand_remove(struct platform_device *pdev) | |||
1190 | return 0; | 1194 | return 0; |
1191 | } | 1195 | } |
1192 | 1196 | ||
1193 | #ifdef CONFIG_PM | 1197 | #ifdef CONFIG_PM_SLEEP |
1194 | static int fsmc_nand_suspend(struct device *dev) | 1198 | static int fsmc_nand_suspend(struct device *dev) |
1195 | { | 1199 | { |
1196 | struct fsmc_nand_data *host = dev_get_drvdata(dev); | 1200 | struct fsmc_nand_data *host = dev_get_drvdata(dev); |
@@ -1210,9 +1214,9 @@ static int fsmc_nand_resume(struct device *dev) | |||
1210 | } | 1214 | } |
1211 | return 0; | 1215 | return 0; |
1212 | } | 1216 | } |
1217 | #endif | ||
1213 | 1218 | ||
1214 | static SIMPLE_DEV_PM_OPS(fsmc_nand_pm_ops, fsmc_nand_suspend, fsmc_nand_resume); | 1219 | static SIMPLE_DEV_PM_OPS(fsmc_nand_pm_ops, fsmc_nand_suspend, fsmc_nand_resume); |
1215 | #endif | ||
1216 | 1220 | ||
1217 | #ifdef CONFIG_OF | 1221 | #ifdef CONFIG_OF |
1218 | static const struct of_device_id fsmc_nand_id_table[] = { | 1222 | static const struct of_device_id fsmc_nand_id_table[] = { |
@@ -1229,9 +1233,7 @@ static struct platform_driver fsmc_nand_driver = { | |||
1229 | .owner = THIS_MODULE, | 1233 | .owner = THIS_MODULE, |
1230 | .name = "fsmc-nand", | 1234 | .name = "fsmc-nand", |
1231 | .of_match_table = of_match_ptr(fsmc_nand_id_table), | 1235 | .of_match_table = of_match_ptr(fsmc_nand_id_table), |
1232 | #ifdef CONFIG_PM | ||
1233 | .pm = &fsmc_nand_pm_ops, | 1236 | .pm = &fsmc_nand_pm_ops, |
1234 | #endif | ||
1235 | }, | 1237 | }, |
1236 | }; | 1238 | }; |
1237 | 1239 | ||
diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c index 89065dd83d64..e826f898241f 100644 --- a/drivers/mtd/nand/gpio.c +++ b/drivers/mtd/nand/gpio.c | |||
@@ -17,6 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/err.h> | ||
20 | #include <linux/init.h> | 21 | #include <linux/init.h> |
21 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
22 | #include <linux/module.h> | 23 | #include <linux/module.h> |
@@ -86,59 +87,11 @@ static void gpio_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) | |||
86 | gpio_nand_dosync(gpiomtd); | 87 | gpio_nand_dosync(gpiomtd); |
87 | } | 88 | } |
88 | 89 | ||
89 | static void gpio_nand_writebuf(struct mtd_info *mtd, const u_char *buf, int len) | ||
90 | { | ||
91 | struct nand_chip *this = mtd->priv; | ||
92 | |||
93 | iowrite8_rep(this->IO_ADDR_W, buf, len); | ||
94 | } | ||
95 | |||
96 | static void gpio_nand_readbuf(struct mtd_info *mtd, u_char *buf, int len) | ||
97 | { | ||
98 | struct nand_chip *this = mtd->priv; | ||
99 | |||
100 | ioread8_rep(this->IO_ADDR_R, buf, len); | ||
101 | } | ||
102 | |||
103 | static void gpio_nand_writebuf16(struct mtd_info *mtd, const u_char *buf, | ||
104 | int len) | ||
105 | { | ||
106 | struct nand_chip *this = mtd->priv; | ||
107 | |||
108 | if (IS_ALIGNED((unsigned long)buf, 2)) { | ||
109 | iowrite16_rep(this->IO_ADDR_W, buf, len>>1); | ||
110 | } else { | ||
111 | int i; | ||
112 | unsigned short *ptr = (unsigned short *)buf; | ||
113 | |||
114 | for (i = 0; i < len; i += 2, ptr++) | ||
115 | writew(*ptr, this->IO_ADDR_W); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | static void gpio_nand_readbuf16(struct mtd_info *mtd, u_char *buf, int len) | ||
120 | { | ||
121 | struct nand_chip *this = mtd->priv; | ||
122 | |||
123 | if (IS_ALIGNED((unsigned long)buf, 2)) { | ||
124 | ioread16_rep(this->IO_ADDR_R, buf, len>>1); | ||
125 | } else { | ||
126 | int i; | ||
127 | unsigned short *ptr = (unsigned short *)buf; | ||
128 | |||
129 | for (i = 0; i < len; i += 2, ptr++) | ||
130 | *ptr = readw(this->IO_ADDR_R); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static int gpio_nand_devready(struct mtd_info *mtd) | 90 | static int gpio_nand_devready(struct mtd_info *mtd) |
135 | { | 91 | { |
136 | struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd); | 92 | struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd); |
137 | 93 | ||
138 | if (gpio_is_valid(gpiomtd->plat.gpio_rdy)) | 94 | return gpio_get_value(gpiomtd->plat.gpio_rdy); |
139 | return gpio_get_value(gpiomtd->plat.gpio_rdy); | ||
140 | |||
141 | return 1; | ||
142 | } | 95 | } |
143 | 96 | ||
144 | #ifdef CONFIG_OF | 97 | #ifdef CONFIG_OF |
@@ -153,6 +106,9 @@ static int gpio_nand_get_config_of(const struct device *dev, | |||
153 | { | 106 | { |
154 | u32 val; | 107 | u32 val; |
155 | 108 | ||
109 | if (!dev->of_node) | ||
110 | return -ENODEV; | ||
111 | |||
156 | if (!of_property_read_u32(dev->of_node, "bank-width", &val)) { | 112 | if (!of_property_read_u32(dev->of_node, "bank-width", &val)) { |
157 | if (val == 2) { | 113 | if (val == 2) { |
158 | plat->options |= NAND_BUSWIDTH_16; | 114 | plat->options |= NAND_BUSWIDTH_16; |
@@ -211,8 +167,8 @@ static inline int gpio_nand_get_config(const struct device *dev, | |||
211 | if (!ret) | 167 | if (!ret) |
212 | return ret; | 168 | return ret; |
213 | 169 | ||
214 | if (dev->platform_data) { | 170 | if (dev_get_platdata(dev)) { |
215 | memcpy(plat, dev->platform_data, sizeof(*plat)); | 171 | memcpy(plat, dev_get_platdata(dev), sizeof(*plat)); |
216 | return 0; | 172 | return 0; |
217 | } | 173 | } |
218 | 174 | ||
@@ -230,145 +186,100 @@ gpio_nand_get_io_sync(struct platform_device *pdev) | |||
230 | return platform_get_resource(pdev, IORESOURCE_MEM, 1); | 186 | return platform_get_resource(pdev, IORESOURCE_MEM, 1); |
231 | } | 187 | } |
232 | 188 | ||
233 | static int gpio_nand_remove(struct platform_device *dev) | 189 | static int gpio_nand_remove(struct platform_device *pdev) |
234 | { | 190 | { |
235 | struct gpiomtd *gpiomtd = platform_get_drvdata(dev); | 191 | struct gpiomtd *gpiomtd = platform_get_drvdata(pdev); |
236 | struct resource *res; | ||
237 | 192 | ||
238 | nand_release(&gpiomtd->mtd_info); | 193 | nand_release(&gpiomtd->mtd_info); |
239 | 194 | ||
240 | res = gpio_nand_get_io_sync(dev); | ||
241 | iounmap(gpiomtd->io_sync); | ||
242 | if (res) | ||
243 | release_mem_region(res->start, resource_size(res)); | ||
244 | |||
245 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
246 | iounmap(gpiomtd->nand_chip.IO_ADDR_R); | ||
247 | release_mem_region(res->start, resource_size(res)); | ||
248 | |||
249 | if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) | 195 | if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) |
250 | gpio_set_value(gpiomtd->plat.gpio_nwp, 0); | 196 | gpio_set_value(gpiomtd->plat.gpio_nwp, 0); |
251 | gpio_set_value(gpiomtd->plat.gpio_nce, 1); | 197 | gpio_set_value(gpiomtd->plat.gpio_nce, 1); |
252 | 198 | ||
253 | gpio_free(gpiomtd->plat.gpio_cle); | ||
254 | gpio_free(gpiomtd->plat.gpio_ale); | ||
255 | gpio_free(gpiomtd->plat.gpio_nce); | ||
256 | if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) | ||
257 | gpio_free(gpiomtd->plat.gpio_nwp); | ||
258 | if (gpio_is_valid(gpiomtd->plat.gpio_rdy)) | ||
259 | gpio_free(gpiomtd->plat.gpio_rdy); | ||
260 | |||
261 | return 0; | 199 | return 0; |
262 | } | 200 | } |
263 | 201 | ||
264 | static void __iomem *request_and_remap(struct resource *res, size_t size, | 202 | static int gpio_nand_probe(struct platform_device *pdev) |
265 | const char *name, int *err) | ||
266 | { | ||
267 | void __iomem *ptr; | ||
268 | |||
269 | if (!request_mem_region(res->start, resource_size(res), name)) { | ||
270 | *err = -EBUSY; | ||
271 | return NULL; | ||
272 | } | ||
273 | |||
274 | ptr = ioremap(res->start, size); | ||
275 | if (!ptr) { | ||
276 | release_mem_region(res->start, resource_size(res)); | ||
277 | *err = -ENOMEM; | ||
278 | } | ||
279 | return ptr; | ||
280 | } | ||
281 | |||
282 | static int gpio_nand_probe(struct platform_device *dev) | ||
283 | { | 203 | { |
284 | struct gpiomtd *gpiomtd; | 204 | struct gpiomtd *gpiomtd; |
285 | struct nand_chip *this; | 205 | struct nand_chip *chip; |
286 | struct resource *res0, *res1; | 206 | struct resource *res; |
287 | struct mtd_part_parser_data ppdata = {}; | 207 | struct mtd_part_parser_data ppdata = {}; |
288 | int ret = 0; | 208 | int ret = 0; |
289 | 209 | ||
290 | if (!dev->dev.of_node && !dev->dev.platform_data) | 210 | if (!pdev->dev.of_node && !dev_get_platdata(&pdev->dev)) |
291 | return -EINVAL; | ||
292 | |||
293 | res0 = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
294 | if (!res0) | ||
295 | return -EINVAL; | 211 | return -EINVAL; |
296 | 212 | ||
297 | gpiomtd = devm_kzalloc(&dev->dev, sizeof(*gpiomtd), GFP_KERNEL); | 213 | gpiomtd = devm_kzalloc(&pdev->dev, sizeof(*gpiomtd), GFP_KERNEL); |
298 | if (gpiomtd == NULL) { | 214 | if (!gpiomtd) { |
299 | dev_err(&dev->dev, "failed to create NAND MTD\n"); | 215 | dev_err(&pdev->dev, "failed to create NAND MTD\n"); |
300 | return -ENOMEM; | 216 | return -ENOMEM; |
301 | } | 217 | } |
302 | 218 | ||
303 | this = &gpiomtd->nand_chip; | 219 | chip = &gpiomtd->nand_chip; |
304 | this->IO_ADDR_R = request_and_remap(res0, 2, "NAND", &ret); | ||
305 | if (!this->IO_ADDR_R) { | ||
306 | dev_err(&dev->dev, "unable to map NAND\n"); | ||
307 | goto err_map; | ||
308 | } | ||
309 | 220 | ||
310 | res1 = gpio_nand_get_io_sync(dev); | 221 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
311 | if (res1) { | 222 | chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res); |
312 | gpiomtd->io_sync = request_and_remap(res1, 4, "NAND sync", &ret); | 223 | if (IS_ERR(chip->IO_ADDR_R)) |
313 | if (!gpiomtd->io_sync) { | 224 | return PTR_ERR(chip->IO_ADDR_R); |
314 | dev_err(&dev->dev, "unable to map sync NAND\n"); | 225 | |
315 | goto err_sync; | 226 | res = gpio_nand_get_io_sync(pdev); |
316 | } | 227 | if (res) { |
228 | gpiomtd->io_sync = devm_ioremap_resource(&pdev->dev, res); | ||
229 | if (IS_ERR(gpiomtd->io_sync)) | ||
230 | return PTR_ERR(gpiomtd->io_sync); | ||
317 | } | 231 | } |
318 | 232 | ||
319 | ret = gpio_nand_get_config(&dev->dev, &gpiomtd->plat); | 233 | ret = gpio_nand_get_config(&pdev->dev, &gpiomtd->plat); |
320 | if (ret) | 234 | if (ret) |
321 | goto err_nce; | 235 | return ret; |
322 | 236 | ||
323 | ret = gpio_request(gpiomtd->plat.gpio_nce, "NAND NCE"); | 237 | ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_nce, "NAND NCE"); |
324 | if (ret) | 238 | if (ret) |
325 | goto err_nce; | 239 | return ret; |
326 | gpio_direction_output(gpiomtd->plat.gpio_nce, 1); | 240 | gpio_direction_output(gpiomtd->plat.gpio_nce, 1); |
241 | |||
327 | if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) { | 242 | if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) { |
328 | ret = gpio_request(gpiomtd->plat.gpio_nwp, "NAND NWP"); | 243 | ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_nwp, |
244 | "NAND NWP"); | ||
329 | if (ret) | 245 | if (ret) |
330 | goto err_nwp; | 246 | return ret; |
331 | gpio_direction_output(gpiomtd->plat.gpio_nwp, 1); | ||
332 | } | 247 | } |
333 | ret = gpio_request(gpiomtd->plat.gpio_ale, "NAND ALE"); | 248 | |
249 | ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_ale, "NAND ALE"); | ||
334 | if (ret) | 250 | if (ret) |
335 | goto err_ale; | 251 | return ret; |
336 | gpio_direction_output(gpiomtd->plat.gpio_ale, 0); | 252 | gpio_direction_output(gpiomtd->plat.gpio_ale, 0); |
337 | ret = gpio_request(gpiomtd->plat.gpio_cle, "NAND CLE"); | 253 | |
254 | ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_cle, "NAND CLE"); | ||
338 | if (ret) | 255 | if (ret) |
339 | goto err_cle; | 256 | return ret; |
340 | gpio_direction_output(gpiomtd->plat.gpio_cle, 0); | 257 | gpio_direction_output(gpiomtd->plat.gpio_cle, 0); |
258 | |||
341 | if (gpio_is_valid(gpiomtd->plat.gpio_rdy)) { | 259 | if (gpio_is_valid(gpiomtd->plat.gpio_rdy)) { |
342 | ret = gpio_request(gpiomtd->plat.gpio_rdy, "NAND RDY"); | 260 | ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_rdy, |
261 | "NAND RDY"); | ||
343 | if (ret) | 262 | if (ret) |
344 | goto err_rdy; | 263 | return ret; |
345 | gpio_direction_input(gpiomtd->plat.gpio_rdy); | 264 | gpio_direction_input(gpiomtd->plat.gpio_rdy); |
265 | chip->dev_ready = gpio_nand_devready; | ||
346 | } | 266 | } |
347 | 267 | ||
268 | chip->IO_ADDR_W = chip->IO_ADDR_R; | ||
269 | chip->ecc.mode = NAND_ECC_SOFT; | ||
270 | chip->options = gpiomtd->plat.options; | ||
271 | chip->chip_delay = gpiomtd->plat.chip_delay; | ||
272 | chip->cmd_ctrl = gpio_nand_cmd_ctrl; | ||
348 | 273 | ||
349 | this->IO_ADDR_W = this->IO_ADDR_R; | 274 | gpiomtd->mtd_info.priv = chip; |
350 | this->ecc.mode = NAND_ECC_SOFT; | 275 | gpiomtd->mtd_info.owner = THIS_MODULE; |
351 | this->options = gpiomtd->plat.options; | ||
352 | this->chip_delay = gpiomtd->plat.chip_delay; | ||
353 | |||
354 | /* install our routines */ | ||
355 | this->cmd_ctrl = gpio_nand_cmd_ctrl; | ||
356 | this->dev_ready = gpio_nand_devready; | ||
357 | 276 | ||
358 | if (this->options & NAND_BUSWIDTH_16) { | 277 | platform_set_drvdata(pdev, gpiomtd); |
359 | this->read_buf = gpio_nand_readbuf16; | ||
360 | this->write_buf = gpio_nand_writebuf16; | ||
361 | } else { | ||
362 | this->read_buf = gpio_nand_readbuf; | ||
363 | this->write_buf = gpio_nand_writebuf; | ||
364 | } | ||
365 | 278 | ||
366 | /* set the mtd private data for the nand driver */ | 279 | if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) |
367 | gpiomtd->mtd_info.priv = this; | 280 | gpio_direction_output(gpiomtd->plat.gpio_nwp, 1); |
368 | gpiomtd->mtd_info.owner = THIS_MODULE; | ||
369 | 281 | ||
370 | if (nand_scan(&gpiomtd->mtd_info, 1)) { | 282 | if (nand_scan(&gpiomtd->mtd_info, 1)) { |
371 | dev_err(&dev->dev, "no nand chips found?\n"); | ||
372 | ret = -ENXIO; | 283 | ret = -ENXIO; |
373 | goto err_wp; | 284 | goto err_wp; |
374 | } | 285 | } |
@@ -377,38 +288,17 @@ static int gpio_nand_probe(struct platform_device *dev) | |||
377 | gpiomtd->plat.adjust_parts(&gpiomtd->plat, | 288 | gpiomtd->plat.adjust_parts(&gpiomtd->plat, |
378 | gpiomtd->mtd_info.size); | 289 | gpiomtd->mtd_info.size); |
379 | 290 | ||
380 | ppdata.of_node = dev->dev.of_node; | 291 | ppdata.of_node = pdev->dev.of_node; |
381 | ret = mtd_device_parse_register(&gpiomtd->mtd_info, NULL, &ppdata, | 292 | ret = mtd_device_parse_register(&gpiomtd->mtd_info, NULL, &ppdata, |
382 | gpiomtd->plat.parts, | 293 | gpiomtd->plat.parts, |
383 | gpiomtd->plat.num_parts); | 294 | gpiomtd->plat.num_parts); |
384 | if (ret) | 295 | if (!ret) |
385 | goto err_wp; | 296 | return 0; |
386 | platform_set_drvdata(dev, gpiomtd); | ||
387 | |||
388 | return 0; | ||
389 | 297 | ||
390 | err_wp: | 298 | err_wp: |
391 | if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) | 299 | if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) |
392 | gpio_set_value(gpiomtd->plat.gpio_nwp, 0); | 300 | gpio_set_value(gpiomtd->plat.gpio_nwp, 0); |
393 | if (gpio_is_valid(gpiomtd->plat.gpio_rdy)) | 301 | |
394 | gpio_free(gpiomtd->plat.gpio_rdy); | ||
395 | err_rdy: | ||
396 | gpio_free(gpiomtd->plat.gpio_cle); | ||
397 | err_cle: | ||
398 | gpio_free(gpiomtd->plat.gpio_ale); | ||
399 | err_ale: | ||
400 | if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) | ||
401 | gpio_free(gpiomtd->plat.gpio_nwp); | ||
402 | err_nwp: | ||
403 | gpio_free(gpiomtd->plat.gpio_nce); | ||
404 | err_nce: | ||
405 | iounmap(gpiomtd->io_sync); | ||
406 | if (res1) | ||
407 | release_mem_region(res1->start, resource_size(res1)); | ||
408 | err_sync: | ||
409 | iounmap(gpiomtd->nand_chip.IO_ADDR_R); | ||
410 | release_mem_region(res0->start, resource_size(res0)); | ||
411 | err_map: | ||
412 | return ret; | 302 | return ret; |
413 | } | 303 | } |
414 | 304 | ||
@@ -417,6 +307,7 @@ static struct platform_driver gpio_nand_driver = { | |||
417 | .remove = gpio_nand_remove, | 307 | .remove = gpio_nand_remove, |
418 | .driver = { | 308 | .driver = { |
419 | .name = "gpio-nand", | 309 | .name = "gpio-nand", |
310 | .owner = THIS_MODULE, | ||
420 | .of_match_table = of_match_ptr(gpio_nand_id_table), | 311 | .of_match_table = of_match_ptr(gpio_nand_id_table), |
421 | }, | 312 | }, |
422 | }; | 313 | }; |
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 25ecfa1822a8..59ab0692f0b9 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/mtd/partitions.h> | 28 | #include <linux/mtd/partitions.h> |
29 | #include <linux/pinctrl/consumer.h> | ||
30 | #include <linux/of.h> | 29 | #include <linux/of.h> |
31 | #include <linux/of_device.h> | 30 | #include <linux/of_device.h> |
32 | #include <linux/of_mtd.h> | 31 | #include <linux/of_mtd.h> |
@@ -112,7 +111,131 @@ static inline bool gpmi_check_ecc(struct gpmi_nand_data *this) | |||
112 | return true; | 111 | return true; |
113 | } | 112 | } |
114 | 113 | ||
115 | int common_nfc_set_geometry(struct gpmi_nand_data *this) | 114 | /* |
115 | * If we can get the ECC information from the nand chip, we do not | ||
116 | * need to calculate them ourselves. | ||
117 | * | ||
118 | * We may have available oob space in this case. | ||
119 | */ | ||
120 | static bool set_geometry_by_ecc_info(struct gpmi_nand_data *this) | ||
121 | { | ||
122 | struct bch_geometry *geo = &this->bch_geometry; | ||
123 | struct mtd_info *mtd = &this->mtd; | ||
124 | struct nand_chip *chip = mtd->priv; | ||
125 | struct nand_oobfree *of = gpmi_hw_ecclayout.oobfree; | ||
126 | unsigned int block_mark_bit_offset; | ||
127 | |||
128 | if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0)) | ||
129 | return false; | ||
130 | |||
131 | switch (chip->ecc_step_ds) { | ||
132 | case SZ_512: | ||
133 | geo->gf_len = 13; | ||
134 | break; | ||
135 | case SZ_1K: | ||
136 | geo->gf_len = 14; | ||
137 | break; | ||
138 | default: | ||
139 | dev_err(this->dev, | ||
140 | "unsupported nand chip. ecc bits : %d, ecc size : %d\n", | ||
141 | chip->ecc_strength_ds, chip->ecc_step_ds); | ||
142 | return false; | ||
143 | } | ||
144 | geo->ecc_chunk_size = chip->ecc_step_ds; | ||
145 | geo->ecc_strength = round_up(chip->ecc_strength_ds, 2); | ||
146 | if (!gpmi_check_ecc(this)) | ||
147 | return false; | ||
148 | |||
149 | /* Keep the C >= O */ | ||
150 | if (geo->ecc_chunk_size < mtd->oobsize) { | ||
151 | dev_err(this->dev, | ||
152 | "unsupported nand chip. ecc size: %d, oob size : %d\n", | ||
153 | chip->ecc_step_ds, mtd->oobsize); | ||
154 | return false; | ||
155 | } | ||
156 | |||
157 | /* The default value, see comment in the legacy_set_geometry(). */ | ||
158 | geo->metadata_size = 10; | ||
159 | |||
160 | geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size; | ||
161 | |||
162 | /* | ||
163 | * Now, the NAND chip with 2K page(data chunk is 512byte) shows below: | ||
164 | * | ||
165 | * | P | | ||
166 | * |<----------------------------------------------------->| | ||
167 | * | | | ||
168 | * | (Block Mark) | | ||
169 | * | P' | | | | | ||
170 | * |<-------------------------------------------->| D | | O' | | ||
171 | * | |<---->| |<--->| | ||
172 | * V V V V V | ||
173 | * +---+----------+-+----------+-+----------+-+----------+-+-----+ | ||
174 | * | M | data |E| data |E| data |E| data |E| | | ||
175 | * +---+----------+-+----------+-+----------+-+----------+-+-----+ | ||
176 | * ^ ^ | ||
177 | * | O | | ||
178 | * |<------------>| | ||
179 | * | | | ||
180 | * | ||
181 | * P : the page size for BCH module. | ||
182 | * E : The ECC strength. | ||
183 | * G : the length of Galois Field. | ||
184 | * N : The chunk count of per page. | ||
185 | * M : the metasize of per page. | ||
186 | * C : the ecc chunk size, aka the "data" above. | ||
187 | * P': the nand chip's page size. | ||
188 | * O : the nand chip's oob size. | ||
189 | * O': the free oob. | ||
190 | * | ||
191 | * The formula for P is : | ||
192 | * | ||
193 | * E * G * N | ||
194 | * P = ------------ + P' + M | ||
195 | * 8 | ||
196 | * | ||
197 | * The position of block mark moves forward in the ECC-based view | ||
198 | * of page, and the delta is: | ||
199 | * | ||
200 | * E * G * (N - 1) | ||
201 | * D = (---------------- + M) | ||
202 | * 8 | ||
203 | * | ||
204 | * Please see the comment in legacy_set_geometry(). | ||
205 | * With the condition C >= O , we still can get same result. | ||
206 | * So the bit position of the physical block mark within the ECC-based | ||
207 | * view of the page is : | ||
208 | * (P' - D) * 8 | ||
209 | */ | ||
210 | geo->page_size = mtd->writesize + geo->metadata_size + | ||
211 | (geo->gf_len * geo->ecc_strength * geo->ecc_chunk_count) / 8; | ||
212 | |||
213 | /* The available oob size we have. */ | ||
214 | if (geo->page_size < mtd->writesize + mtd->oobsize) { | ||
215 | of->offset = geo->page_size - mtd->writesize; | ||
216 | of->length = mtd->oobsize - of->offset; | ||
217 | } | ||
218 | |||
219 | geo->payload_size = mtd->writesize; | ||
220 | |||
221 | geo->auxiliary_status_offset = ALIGN(geo->metadata_size, 4); | ||
222 | geo->auxiliary_size = ALIGN(geo->metadata_size, 4) | ||
223 | + ALIGN(geo->ecc_chunk_count, 4); | ||
224 | |||
225 | if (!this->swap_block_mark) | ||
226 | return true; | ||
227 | |||
228 | /* For bit swap. */ | ||
229 | block_mark_bit_offset = mtd->writesize * 8 - | ||
230 | (geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1) | ||
231 | + geo->metadata_size * 8); | ||
232 | |||
233 | geo->block_mark_byte_offset = block_mark_bit_offset / 8; | ||
234 | geo->block_mark_bit_offset = block_mark_bit_offset % 8; | ||
235 | return true; | ||
236 | } | ||
237 | |||
238 | static int legacy_set_geometry(struct gpmi_nand_data *this) | ||
116 | { | 239 | { |
117 | struct bch_geometry *geo = &this->bch_geometry; | 240 | struct bch_geometry *geo = &this->bch_geometry; |
118 | struct mtd_info *mtd = &this->mtd; | 241 | struct mtd_info *mtd = &this->mtd; |
@@ -224,6 +347,11 @@ int common_nfc_set_geometry(struct gpmi_nand_data *this) | |||
224 | return 0; | 347 | return 0; |
225 | } | 348 | } |
226 | 349 | ||
350 | int common_nfc_set_geometry(struct gpmi_nand_data *this) | ||
351 | { | ||
352 | return set_geometry_by_ecc_info(this) ? 0 : legacy_set_geometry(this); | ||
353 | } | ||
354 | |||
227 | struct dma_chan *get_dma_chan(struct gpmi_nand_data *this) | 355 | struct dma_chan *get_dma_chan(struct gpmi_nand_data *this) |
228 | { | 356 | { |
229 | int chipnr = this->current_chip; | 357 | int chipnr = this->current_chip; |
@@ -355,7 +483,7 @@ static int acquire_register_block(struct gpmi_nand_data *this, | |||
355 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name); | 483 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name); |
356 | if (!r) { | 484 | if (!r) { |
357 | pr_err("Can't get resource for %s\n", res_name); | 485 | pr_err("Can't get resource for %s\n", res_name); |
358 | return -ENXIO; | 486 | return -ENODEV; |
359 | } | 487 | } |
360 | 488 | ||
361 | p = ioremap(r->start, resource_size(r)); | 489 | p = ioremap(r->start, resource_size(r)); |
@@ -396,7 +524,7 @@ static int acquire_bch_irq(struct gpmi_nand_data *this, irq_handler_t irq_h) | |||
396 | r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name); | 524 | r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name); |
397 | if (!r) { | 525 | if (!r) { |
398 | pr_err("Can't get resource for %s\n", res_name); | 526 | pr_err("Can't get resource for %s\n", res_name); |
399 | return -ENXIO; | 527 | return -ENODEV; |
400 | } | 528 | } |
401 | 529 | ||
402 | err = request_irq(r->start, irq_h, 0, res_name, this); | 530 | err = request_irq(r->start, irq_h, 0, res_name, this); |
@@ -473,12 +601,14 @@ static int gpmi_get_clks(struct gpmi_nand_data *this) | |||
473 | struct resources *r = &this->resources; | 601 | struct resources *r = &this->resources; |
474 | char **extra_clks = NULL; | 602 | char **extra_clks = NULL; |
475 | struct clk *clk; | 603 | struct clk *clk; |
476 | int i; | 604 | int err, i; |
477 | 605 | ||
478 | /* The main clock is stored in the first. */ | 606 | /* The main clock is stored in the first. */ |
479 | r->clock[0] = clk_get(this->dev, "gpmi_io"); | 607 | r->clock[0] = clk_get(this->dev, "gpmi_io"); |
480 | if (IS_ERR(r->clock[0])) | 608 | if (IS_ERR(r->clock[0])) { |
609 | err = PTR_ERR(r->clock[0]); | ||
481 | goto err_clock; | 610 | goto err_clock; |
611 | } | ||
482 | 612 | ||
483 | /* Get extra clocks */ | 613 | /* Get extra clocks */ |
484 | if (GPMI_IS_MX6Q(this)) | 614 | if (GPMI_IS_MX6Q(this)) |
@@ -491,8 +621,10 @@ static int gpmi_get_clks(struct gpmi_nand_data *this) | |||
491 | break; | 621 | break; |
492 | 622 | ||
493 | clk = clk_get(this->dev, extra_clks[i - 1]); | 623 | clk = clk_get(this->dev, extra_clks[i - 1]); |
494 | if (IS_ERR(clk)) | 624 | if (IS_ERR(clk)) { |
625 | err = PTR_ERR(clk); | ||
495 | goto err_clock; | 626 | goto err_clock; |
627 | } | ||
496 | 628 | ||
497 | r->clock[i] = clk; | 629 | r->clock[i] = clk; |
498 | } | 630 | } |
@@ -511,12 +643,11 @@ static int gpmi_get_clks(struct gpmi_nand_data *this) | |||
511 | err_clock: | 643 | err_clock: |
512 | dev_dbg(this->dev, "failed in finding the clocks.\n"); | 644 | dev_dbg(this->dev, "failed in finding the clocks.\n"); |
513 | gpmi_put_clks(this); | 645 | gpmi_put_clks(this); |
514 | return -ENOMEM; | 646 | return err; |
515 | } | 647 | } |
516 | 648 | ||
517 | static int acquire_resources(struct gpmi_nand_data *this) | 649 | static int acquire_resources(struct gpmi_nand_data *this) |
518 | { | 650 | { |
519 | struct pinctrl *pinctrl; | ||
520 | int ret; | 651 | int ret; |
521 | 652 | ||
522 | ret = acquire_register_block(this, GPMI_NAND_GPMI_REGS_ADDR_RES_NAME); | 653 | ret = acquire_register_block(this, GPMI_NAND_GPMI_REGS_ADDR_RES_NAME); |
@@ -535,19 +666,12 @@ static int acquire_resources(struct gpmi_nand_data *this) | |||
535 | if (ret) | 666 | if (ret) |
536 | goto exit_dma_channels; | 667 | goto exit_dma_channels; |
537 | 668 | ||
538 | pinctrl = devm_pinctrl_get_select_default(&this->pdev->dev); | ||
539 | if (IS_ERR(pinctrl)) { | ||
540 | ret = PTR_ERR(pinctrl); | ||
541 | goto exit_pin; | ||
542 | } | ||
543 | |||
544 | ret = gpmi_get_clks(this); | 669 | ret = gpmi_get_clks(this); |
545 | if (ret) | 670 | if (ret) |
546 | goto exit_clock; | 671 | goto exit_clock; |
547 | return 0; | 672 | return 0; |
548 | 673 | ||
549 | exit_clock: | 674 | exit_clock: |
550 | exit_pin: | ||
551 | release_dma_channels(this); | 675 | release_dma_channels(this); |
552 | exit_dma_channels: | 676 | exit_dma_channels: |
553 | release_bch_irq(this); | 677 | release_bch_irq(this); |
@@ -1153,43 +1277,31 @@ static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
1153 | { | 1277 | { |
1154 | struct nand_chip *chip = mtd->priv; | 1278 | struct nand_chip *chip = mtd->priv; |
1155 | struct gpmi_nand_data *this = chip->priv; | 1279 | struct gpmi_nand_data *this = chip->priv; |
1156 | int block, ret = 0; | 1280 | int ret = 0; |
1157 | uint8_t *block_mark; | 1281 | uint8_t *block_mark; |
1158 | int column, page, status, chipnr; | 1282 | int column, page, status, chipnr; |
1159 | 1283 | ||
1160 | /* Get block number */ | 1284 | chipnr = (int)(ofs >> chip->chip_shift); |
1161 | block = (int)(ofs >> chip->bbt_erase_shift); | 1285 | chip->select_chip(mtd, chipnr); |
1162 | if (chip->bbt) | ||
1163 | chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); | ||
1164 | 1286 | ||
1165 | /* Do we have a flash based bad block table ? */ | 1287 | column = this->swap_block_mark ? mtd->writesize : 0; |
1166 | if (chip->bbt_options & NAND_BBT_USE_FLASH) | ||
1167 | ret = nand_update_bbt(mtd, ofs); | ||
1168 | else { | ||
1169 | chipnr = (int)(ofs >> chip->chip_shift); | ||
1170 | chip->select_chip(mtd, chipnr); | ||
1171 | 1288 | ||
1172 | column = this->swap_block_mark ? mtd->writesize : 0; | 1289 | /* Write the block mark. */ |
1290 | block_mark = this->data_buffer_dma; | ||
1291 | block_mark[0] = 0; /* bad block marker */ | ||
1173 | 1292 | ||
1174 | /* Write the block mark. */ | 1293 | /* Shift to get page */ |
1175 | block_mark = this->data_buffer_dma; | 1294 | page = (int)(ofs >> chip->page_shift); |
1176 | block_mark[0] = 0; /* bad block marker */ | ||
1177 | 1295 | ||
1178 | /* Shift to get page */ | 1296 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, column, page); |
1179 | page = (int)(ofs >> chip->page_shift); | 1297 | chip->write_buf(mtd, block_mark, 1); |
1298 | chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); | ||
1180 | 1299 | ||
1181 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, column, page); | 1300 | status = chip->waitfunc(mtd, chip); |
1182 | chip->write_buf(mtd, block_mark, 1); | 1301 | if (status & NAND_STATUS_FAIL) |
1183 | chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); | 1302 | ret = -EIO; |
1184 | 1303 | ||
1185 | status = chip->waitfunc(mtd, chip); | 1304 | chip->select_chip(mtd, -1); |
1186 | if (status & NAND_STATUS_FAIL) | ||
1187 | ret = -EIO; | ||
1188 | |||
1189 | chip->select_chip(mtd, -1); | ||
1190 | } | ||
1191 | if (!ret) | ||
1192 | mtd->ecc_stats.badblocks++; | ||
1193 | 1305 | ||
1194 | return ret; | 1306 | return ret; |
1195 | } | 1307 | } |
@@ -1469,19 +1581,22 @@ static int gpmi_pre_bbt_scan(struct gpmi_nand_data *this) | |||
1469 | if (ret) | 1581 | if (ret) |
1470 | return ret; | 1582 | return ret; |
1471 | 1583 | ||
1472 | /* Adjust the ECC strength according to the chip. */ | ||
1473 | this->nand.ecc.strength = this->bch_geometry.ecc_strength; | ||
1474 | this->mtd.ecc_strength = this->bch_geometry.ecc_strength; | ||
1475 | this->mtd.bitflip_threshold = this->bch_geometry.ecc_strength; | ||
1476 | |||
1477 | /* NAND boot init, depends on the gpmi_set_geometry(). */ | 1584 | /* NAND boot init, depends on the gpmi_set_geometry(). */ |
1478 | return nand_boot_init(this); | 1585 | return nand_boot_init(this); |
1479 | } | 1586 | } |
1480 | 1587 | ||
1481 | static int gpmi_scan_bbt(struct mtd_info *mtd) | 1588 | static void gpmi_nfc_exit(struct gpmi_nand_data *this) |
1482 | { | 1589 | { |
1590 | nand_release(&this->mtd); | ||
1591 | gpmi_free_dma_buffer(this); | ||
1592 | } | ||
1593 | |||
1594 | static int gpmi_init_last(struct gpmi_nand_data *this) | ||
1595 | { | ||
1596 | struct mtd_info *mtd = &this->mtd; | ||
1483 | struct nand_chip *chip = mtd->priv; | 1597 | struct nand_chip *chip = mtd->priv; |
1484 | struct gpmi_nand_data *this = chip->priv; | 1598 | struct nand_ecc_ctrl *ecc = &chip->ecc; |
1599 | struct bch_geometry *bch_geo = &this->bch_geometry; | ||
1485 | int ret; | 1600 | int ret; |
1486 | 1601 | ||
1487 | /* Prepare for the BBT scan. */ | 1602 | /* Prepare for the BBT scan. */ |
@@ -1489,6 +1604,16 @@ static int gpmi_scan_bbt(struct mtd_info *mtd) | |||
1489 | if (ret) | 1604 | if (ret) |
1490 | return ret; | 1605 | return ret; |
1491 | 1606 | ||
1607 | /* Init the nand_ecc_ctrl{} */ | ||
1608 | ecc->read_page = gpmi_ecc_read_page; | ||
1609 | ecc->write_page = gpmi_ecc_write_page; | ||
1610 | ecc->read_oob = gpmi_ecc_read_oob; | ||
1611 | ecc->write_oob = gpmi_ecc_write_oob; | ||
1612 | ecc->mode = NAND_ECC_HW; | ||
1613 | ecc->size = bch_geo->ecc_chunk_size; | ||
1614 | ecc->strength = bch_geo->ecc_strength; | ||
1615 | ecc->layout = &gpmi_hw_ecclayout; | ||
1616 | |||
1492 | /* | 1617 | /* |
1493 | * Can we enable the extra features? such as EDO or Sync mode. | 1618 | * Can we enable the extra features? such as EDO or Sync mode. |
1494 | * | 1619 | * |
@@ -1497,14 +1622,7 @@ static int gpmi_scan_bbt(struct mtd_info *mtd) | |||
1497 | */ | 1622 | */ |
1498 | gpmi_extra_init(this); | 1623 | gpmi_extra_init(this); |
1499 | 1624 | ||
1500 | /* use the default BBT implementation */ | 1625 | return 0; |
1501 | return nand_default_bbt(mtd); | ||
1502 | } | ||
1503 | |||
1504 | static void gpmi_nfc_exit(struct gpmi_nand_data *this) | ||
1505 | { | ||
1506 | nand_release(&this->mtd); | ||
1507 | gpmi_free_dma_buffer(this); | ||
1508 | } | 1626 | } |
1509 | 1627 | ||
1510 | static int gpmi_nfc_init(struct gpmi_nand_data *this) | 1628 | static int gpmi_nfc_init(struct gpmi_nand_data *this) |
@@ -1530,33 +1648,33 @@ static int gpmi_nfc_init(struct gpmi_nand_data *this) | |||
1530 | chip->read_byte = gpmi_read_byte; | 1648 | chip->read_byte = gpmi_read_byte; |
1531 | chip->read_buf = gpmi_read_buf; | 1649 | chip->read_buf = gpmi_read_buf; |
1532 | chip->write_buf = gpmi_write_buf; | 1650 | chip->write_buf = gpmi_write_buf; |
1533 | chip->ecc.read_page = gpmi_ecc_read_page; | ||
1534 | chip->ecc.write_page = gpmi_ecc_write_page; | ||
1535 | chip->ecc.read_oob = gpmi_ecc_read_oob; | ||
1536 | chip->ecc.write_oob = gpmi_ecc_write_oob; | ||
1537 | chip->scan_bbt = gpmi_scan_bbt; | ||
1538 | chip->badblock_pattern = &gpmi_bbt_descr; | 1651 | chip->badblock_pattern = &gpmi_bbt_descr; |
1539 | chip->block_markbad = gpmi_block_markbad; | 1652 | chip->block_markbad = gpmi_block_markbad; |
1540 | chip->options |= NAND_NO_SUBPAGE_WRITE; | 1653 | chip->options |= NAND_NO_SUBPAGE_WRITE; |
1541 | chip->ecc.mode = NAND_ECC_HW; | ||
1542 | chip->ecc.size = 1; | ||
1543 | chip->ecc.strength = 8; | ||
1544 | chip->ecc.layout = &gpmi_hw_ecclayout; | ||
1545 | if (of_get_nand_on_flash_bbt(this->dev->of_node)) | 1654 | if (of_get_nand_on_flash_bbt(this->dev->of_node)) |
1546 | chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; | 1655 | chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; |
1547 | 1656 | ||
1548 | /* Allocate a temporary DMA buffer for reading ID in the nand_scan() */ | 1657 | /* |
1658 | * Allocate a temporary DMA buffer for reading ID in the | ||
1659 | * nand_scan_ident(). | ||
1660 | */ | ||
1549 | this->bch_geometry.payload_size = 1024; | 1661 | this->bch_geometry.payload_size = 1024; |
1550 | this->bch_geometry.auxiliary_size = 128; | 1662 | this->bch_geometry.auxiliary_size = 128; |
1551 | ret = gpmi_alloc_dma_buffer(this); | 1663 | ret = gpmi_alloc_dma_buffer(this); |
1552 | if (ret) | 1664 | if (ret) |
1553 | goto err_out; | 1665 | goto err_out; |
1554 | 1666 | ||
1555 | ret = nand_scan(mtd, 1); | 1667 | ret = nand_scan_ident(mtd, 1, NULL); |
1556 | if (ret) { | 1668 | if (ret) |
1557 | pr_err("Chip scan failed\n"); | 1669 | goto err_out; |
1670 | |||
1671 | ret = gpmi_init_last(this); | ||
1672 | if (ret) | ||
1673 | goto err_out; | ||
1674 | |||
1675 | ret = nand_scan_tail(mtd); | ||
1676 | if (ret) | ||
1558 | goto err_out; | 1677 | goto err_out; |
1559 | } | ||
1560 | 1678 | ||
1561 | ppdata.of_node = this->pdev->dev.of_node; | 1679 | ppdata.of_node = this->pdev->dev.of_node; |
1562 | ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); | 1680 | ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); |
@@ -1601,7 +1719,7 @@ static int gpmi_nand_probe(struct platform_device *pdev) | |||
1601 | pdev->id_entry = of_id->data; | 1719 | pdev->id_entry = of_id->data; |
1602 | } else { | 1720 | } else { |
1603 | pr_err("Failed to find the right device id.\n"); | 1721 | pr_err("Failed to find the right device id.\n"); |
1604 | return -ENOMEM; | 1722 | return -ENODEV; |
1605 | } | 1723 | } |
1606 | 1724 | ||
1607 | this = kzalloc(sizeof(*this), GFP_KERNEL); | 1725 | this = kzalloc(sizeof(*this), GFP_KERNEL); |
@@ -1633,7 +1751,6 @@ static int gpmi_nand_probe(struct platform_device *pdev) | |||
1633 | exit_nfc_init: | 1751 | exit_nfc_init: |
1634 | release_resources(this); | 1752 | release_resources(this); |
1635 | exit_acquire_resources: | 1753 | exit_acquire_resources: |
1636 | platform_set_drvdata(pdev, NULL); | ||
1637 | dev_err(this->dev, "driver registration failed: %d\n", ret); | 1754 | dev_err(this->dev, "driver registration failed: %d\n", ret); |
1638 | kfree(this); | 1755 | kfree(this); |
1639 | 1756 | ||
@@ -1646,7 +1763,6 @@ static int gpmi_nand_remove(struct platform_device *pdev) | |||
1646 | 1763 | ||
1647 | gpmi_nfc_exit(this); | 1764 | gpmi_nfc_exit(this); |
1648 | release_resources(this); | 1765 | release_resources(this); |
1649 | platform_set_drvdata(pdev, NULL); | ||
1650 | kfree(this); | 1766 | kfree(this); |
1651 | return 0; | 1767 | return 0; |
1652 | } | 1768 | } |
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index b76460eeaf22..a264b888c66c 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c | |||
@@ -411,7 +411,7 @@ static int jz_nand_probe(struct platform_device *pdev) | |||
411 | struct jz_nand *nand; | 411 | struct jz_nand *nand; |
412 | struct nand_chip *chip; | 412 | struct nand_chip *chip; |
413 | struct mtd_info *mtd; | 413 | struct mtd_info *mtd; |
414 | struct jz_nand_platform_data *pdata = pdev->dev.platform_data; | 414 | struct jz_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); |
415 | size_t chipnr, bank_idx; | 415 | size_t chipnr, bank_idx; |
416 | uint8_t nand_maf_id = 0, nand_dev_id = 0; | 416 | uint8_t nand_maf_id = 0, nand_dev_id = 0; |
417 | 417 | ||
@@ -538,7 +538,6 @@ err_unclaim_banks: | |||
538 | err_gpio_busy: | 538 | err_gpio_busy: |
539 | if (pdata && gpio_is_valid(pdata->busy_gpio)) | 539 | if (pdata && gpio_is_valid(pdata->busy_gpio)) |
540 | gpio_free(pdata->busy_gpio); | 540 | gpio_free(pdata->busy_gpio); |
541 | platform_set_drvdata(pdev, NULL); | ||
542 | err_iounmap_mmio: | 541 | err_iounmap_mmio: |
543 | jz_nand_iounmap_resource(nand->mem, nand->base); | 542 | jz_nand_iounmap_resource(nand->mem, nand->base); |
544 | err_free: | 543 | err_free: |
@@ -549,7 +548,7 @@ err_free: | |||
549 | static int jz_nand_remove(struct platform_device *pdev) | 548 | static int jz_nand_remove(struct platform_device *pdev) |
550 | { | 549 | { |
551 | struct jz_nand *nand = platform_get_drvdata(pdev); | 550 | struct jz_nand *nand = platform_get_drvdata(pdev); |
552 | struct jz_nand_platform_data *pdata = pdev->dev.platform_data; | 551 | struct jz_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); |
553 | size_t i; | 552 | size_t i; |
554 | 553 | ||
555 | nand_release(&nand->mtd); | 554 | nand_release(&nand->mtd); |
@@ -570,7 +569,6 @@ static int jz_nand_remove(struct platform_device *pdev) | |||
570 | 569 | ||
571 | jz_nand_iounmap_resource(nand->mem, nand->base); | 570 | jz_nand_iounmap_resource(nand->mem, nand->base); |
572 | 571 | ||
573 | platform_set_drvdata(pdev, NULL); | ||
574 | kfree(nand); | 572 | kfree(nand); |
575 | 573 | ||
576 | return 0; | 574 | return 0; |
diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c index fd1df5e13ae4..f4dd2a887ea5 100644 --- a/drivers/mtd/nand/lpc32xx_mlc.c +++ b/drivers/mtd/nand/lpc32xx_mlc.c | |||
@@ -696,7 +696,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) | |||
696 | } | 696 | } |
697 | lpc32xx_wp_disable(host); | 697 | lpc32xx_wp_disable(host); |
698 | 698 | ||
699 | host->pdata = pdev->dev.platform_data; | 699 | host->pdata = dev_get_platdata(&pdev->dev); |
700 | 700 | ||
701 | nand_chip->priv = host; /* link the private data structures */ | 701 | nand_chip->priv = host; /* link the private data structures */ |
702 | mtd->priv = nand_chip; | 702 | mtd->priv = nand_chip; |
@@ -828,7 +828,6 @@ err_exit3: | |||
828 | err_exit2: | 828 | err_exit2: |
829 | clk_disable(host->clk); | 829 | clk_disable(host->clk); |
830 | clk_put(host->clk); | 830 | clk_put(host->clk); |
831 | platform_set_drvdata(pdev, NULL); | ||
832 | err_exit1: | 831 | err_exit1: |
833 | lpc32xx_wp_enable(host); | 832 | lpc32xx_wp_enable(host); |
834 | gpio_free(host->ncfg->wp_gpio); | 833 | gpio_free(host->ncfg->wp_gpio); |
@@ -851,7 +850,6 @@ static int lpc32xx_nand_remove(struct platform_device *pdev) | |||
851 | 850 | ||
852 | clk_disable(host->clk); | 851 | clk_disable(host->clk); |
853 | clk_put(host->clk); | 852 | clk_put(host->clk); |
854 | platform_set_drvdata(pdev, NULL); | ||
855 | 853 | ||
856 | lpc32xx_wp_enable(host); | 854 | lpc32xx_wp_enable(host); |
857 | gpio_free(host->ncfg->wp_gpio); | 855 | gpio_free(host->ncfg->wp_gpio); |
diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c index be94ed5abefb..add75709d415 100644 --- a/drivers/mtd/nand/lpc32xx_slc.c +++ b/drivers/mtd/nand/lpc32xx_slc.c | |||
@@ -798,7 +798,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) | |||
798 | } | 798 | } |
799 | lpc32xx_wp_disable(host); | 799 | lpc32xx_wp_disable(host); |
800 | 800 | ||
801 | host->pdata = pdev->dev.platform_data; | 801 | host->pdata = dev_get_platdata(&pdev->dev); |
802 | 802 | ||
803 | mtd = &host->mtd; | 803 | mtd = &host->mtd; |
804 | chip = &host->nand_chip; | 804 | chip = &host->nand_chip; |
@@ -936,7 +936,6 @@ err_exit3: | |||
936 | err_exit2: | 936 | err_exit2: |
937 | clk_disable(host->clk); | 937 | clk_disable(host->clk); |
938 | clk_put(host->clk); | 938 | clk_put(host->clk); |
939 | platform_set_drvdata(pdev, NULL); | ||
940 | err_exit1: | 939 | err_exit1: |
941 | lpc32xx_wp_enable(host); | 940 | lpc32xx_wp_enable(host); |
942 | gpio_free(host->ncfg->wp_gpio); | 941 | gpio_free(host->ncfg->wp_gpio); |
@@ -963,7 +962,6 @@ static int lpc32xx_nand_remove(struct platform_device *pdev) | |||
963 | 962 | ||
964 | clk_disable(host->clk); | 963 | clk_disable(host->clk); |
965 | clk_put(host->clk); | 964 | clk_put(host->clk); |
966 | platform_set_drvdata(pdev, NULL); | ||
967 | lpc32xx_wp_enable(host); | 965 | lpc32xx_wp_enable(host); |
968 | gpio_free(host->ncfg->wp_gpio); | 966 | gpio_free(host->ncfg->wp_gpio); |
969 | 967 | ||
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 07e5784e5cd3..ce8242b6c3e7 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -266,7 +266,7 @@ static struct nand_ecclayout nandv2_hw_eccoob_4k = { | |||
266 | } | 266 | } |
267 | }; | 267 | }; |
268 | 268 | ||
269 | static const char const *part_probes[] = { | 269 | static const char * const part_probes[] = { |
270 | "cmdlinepart", "RedBoot", "ofpart", NULL }; | 270 | "cmdlinepart", "RedBoot", "ofpart", NULL }; |
271 | 271 | ||
272 | static void memcpy32_fromio(void *trg, const void __iomem *src, size_t size) | 272 | static void memcpy32_fromio(void *trg, const void __iomem *src, size_t size) |
@@ -1432,7 +1432,8 @@ static int mxcnd_probe(struct platform_device *pdev) | |||
1432 | 1432 | ||
1433 | err = mxcnd_probe_dt(host); | 1433 | err = mxcnd_probe_dt(host); |
1434 | if (err > 0) { | 1434 | if (err > 0) { |
1435 | struct mxc_nand_platform_data *pdata = pdev->dev.platform_data; | 1435 | struct mxc_nand_platform_data *pdata = |
1436 | dev_get_platdata(&pdev->dev); | ||
1436 | if (pdata) { | 1437 | if (pdata) { |
1437 | host->pdata = *pdata; | 1438 | host->pdata = *pdata; |
1438 | host->devtype_data = (struct mxc_nand_devtype_data *) | 1439 | host->devtype_data = (struct mxc_nand_devtype_data *) |
@@ -1446,8 +1447,6 @@ static int mxcnd_probe(struct platform_device *pdev) | |||
1446 | 1447 | ||
1447 | if (host->devtype_data->needs_ip) { | 1448 | if (host->devtype_data->needs_ip) { |
1448 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1449 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1449 | if (!res) | ||
1450 | return -ENODEV; | ||
1451 | host->regs_ip = devm_ioremap_resource(&pdev->dev, res); | 1450 | host->regs_ip = devm_ioremap_resource(&pdev->dev, res); |
1452 | if (IS_ERR(host->regs_ip)) | 1451 | if (IS_ERR(host->regs_ip)) |
1453 | return PTR_ERR(host->regs_ip); | 1452 | return PTR_ERR(host->regs_ip); |
@@ -1457,9 +1456,6 @@ static int mxcnd_probe(struct platform_device *pdev) | |||
1457 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1456 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1458 | } | 1457 | } |
1459 | 1458 | ||
1460 | if (!res) | ||
1461 | return -ENODEV; | ||
1462 | |||
1463 | host->base = devm_ioremap_resource(&pdev->dev, res); | 1459 | host->base = devm_ioremap_resource(&pdev->dev, res); |
1464 | if (IS_ERR(host->base)) | 1460 | if (IS_ERR(host->base)) |
1465 | return PTR_ERR(host->base); | 1461 | return PTR_ERR(host->base); |
@@ -1578,8 +1574,6 @@ static int mxcnd_remove(struct platform_device *pdev) | |||
1578 | { | 1574 | { |
1579 | struct mxc_nand_host *host = platform_get_drvdata(pdev); | 1575 | struct mxc_nand_host *host = platform_get_drvdata(pdev); |
1580 | 1576 | ||
1581 | platform_set_drvdata(pdev, NULL); | ||
1582 | |||
1583 | nand_release(&host->mtd); | 1577 | nand_release(&host->mtd); |
1584 | 1578 | ||
1585 | return 0; | 1579 | return 0; |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index dfcd0a565c5b..7ed4841327f2 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -108,13 +108,13 @@ static int check_offs_len(struct mtd_info *mtd, | |||
108 | int ret = 0; | 108 | int ret = 0; |
109 | 109 | ||
110 | /* Start address must align on block boundary */ | 110 | /* Start address must align on block boundary */ |
111 | if (ofs & ((1 << chip->phys_erase_shift) - 1)) { | 111 | if (ofs & ((1ULL << chip->phys_erase_shift) - 1)) { |
112 | pr_debug("%s: unaligned address\n", __func__); | 112 | pr_debug("%s: unaligned address\n", __func__); |
113 | ret = -EINVAL; | 113 | ret = -EINVAL; |
114 | } | 114 | } |
115 | 115 | ||
116 | /* Length must align on block boundary */ | 116 | /* Length must align on block boundary */ |
117 | if (len & ((1 << chip->phys_erase_shift) - 1)) { | 117 | if (len & ((1ULL << chip->phys_erase_shift) - 1)) { |
118 | pr_debug("%s: length not block aligned\n", __func__); | 118 | pr_debug("%s: length not block aligned\n", __func__); |
119 | ret = -EINVAL; | 119 | ret = -EINVAL; |
120 | } | 120 | } |
@@ -211,11 +211,9 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr) | |||
211 | */ | 211 | */ |
212 | static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | 212 | static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) |
213 | { | 213 | { |
214 | int i; | ||
215 | struct nand_chip *chip = mtd->priv; | 214 | struct nand_chip *chip = mtd->priv; |
216 | 215 | ||
217 | for (i = 0; i < len; i++) | 216 | iowrite8_rep(chip->IO_ADDR_W, buf, len); |
218 | writeb(buf[i], chip->IO_ADDR_W); | ||
219 | } | 217 | } |
220 | 218 | ||
221 | /** | 219 | /** |
@@ -228,11 +226,9 @@ static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | |||
228 | */ | 226 | */ |
229 | static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | 227 | static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) |
230 | { | 228 | { |
231 | int i; | ||
232 | struct nand_chip *chip = mtd->priv; | 229 | struct nand_chip *chip = mtd->priv; |
233 | 230 | ||
234 | for (i = 0; i < len; i++) | 231 | ioread8_rep(chip->IO_ADDR_R, buf, len); |
235 | buf[i] = readb(chip->IO_ADDR_R); | ||
236 | } | 232 | } |
237 | 233 | ||
238 | /** | 234 | /** |
@@ -245,14 +241,10 @@ static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | |||
245 | */ | 241 | */ |
246 | static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) | 242 | static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) |
247 | { | 243 | { |
248 | int i; | ||
249 | struct nand_chip *chip = mtd->priv; | 244 | struct nand_chip *chip = mtd->priv; |
250 | u16 *p = (u16 *) buf; | 245 | u16 *p = (u16 *) buf; |
251 | len >>= 1; | ||
252 | |||
253 | for (i = 0; i < len; i++) | ||
254 | writew(p[i], chip->IO_ADDR_W); | ||
255 | 246 | ||
247 | iowrite16_rep(chip->IO_ADDR_W, p, len >> 1); | ||
256 | } | 248 | } |
257 | 249 | ||
258 | /** | 250 | /** |
@@ -265,13 +257,10 @@ static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len) | |||
265 | */ | 257 | */ |
266 | static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) | 258 | static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) |
267 | { | 259 | { |
268 | int i; | ||
269 | struct nand_chip *chip = mtd->priv; | 260 | struct nand_chip *chip = mtd->priv; |
270 | u16 *p = (u16 *) buf; | 261 | u16 *p = (u16 *) buf; |
271 | len >>= 1; | ||
272 | 262 | ||
273 | for (i = 0; i < len; i++) | 263 | ioread16_rep(chip->IO_ADDR_R, p, len >> 1); |
274 | p[i] = readw(chip->IO_ADDR_R); | ||
275 | } | 264 | } |
276 | 265 | ||
277 | /** | 266 | /** |
@@ -335,80 +324,88 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) | |||
335 | } | 324 | } |
336 | 325 | ||
337 | /** | 326 | /** |
338 | * nand_default_block_markbad - [DEFAULT] mark a block bad | 327 | * nand_default_block_markbad - [DEFAULT] mark a block bad via bad block marker |
339 | * @mtd: MTD device structure | 328 | * @mtd: MTD device structure |
340 | * @ofs: offset from device start | 329 | * @ofs: offset from device start |
341 | * | 330 | * |
342 | * This is the default implementation, which can be overridden by a hardware | 331 | * This is the default implementation, which can be overridden by a hardware |
343 | * specific driver. We try operations in the following order, according to our | 332 | * specific driver. It provides the details for writing a bad block marker to a |
344 | * bbt_options (NAND_BBT_NO_OOB_BBM and NAND_BBT_USE_FLASH): | 333 | * block. |
334 | */ | ||
335 | static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | ||
336 | { | ||
337 | struct nand_chip *chip = mtd->priv; | ||
338 | struct mtd_oob_ops ops; | ||
339 | uint8_t buf[2] = { 0, 0 }; | ||
340 | int ret = 0, res, i = 0; | ||
341 | |||
342 | ops.datbuf = NULL; | ||
343 | ops.oobbuf = buf; | ||
344 | ops.ooboffs = chip->badblockpos; | ||
345 | if (chip->options & NAND_BUSWIDTH_16) { | ||
346 | ops.ooboffs &= ~0x01; | ||
347 | ops.len = ops.ooblen = 2; | ||
348 | } else { | ||
349 | ops.len = ops.ooblen = 1; | ||
350 | } | ||
351 | ops.mode = MTD_OPS_PLACE_OOB; | ||
352 | |||
353 | /* Write to first/last page(s) if necessary */ | ||
354 | if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) | ||
355 | ofs += mtd->erasesize - mtd->writesize; | ||
356 | do { | ||
357 | res = nand_do_write_oob(mtd, ofs, &ops); | ||
358 | if (!ret) | ||
359 | ret = res; | ||
360 | |||
361 | i++; | ||
362 | ofs += mtd->writesize; | ||
363 | } while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2); | ||
364 | |||
365 | return ret; | ||
366 | } | ||
367 | |||
368 | /** | ||
369 | * nand_block_markbad_lowlevel - mark a block bad | ||
370 | * @mtd: MTD device structure | ||
371 | * @ofs: offset from device start | ||
372 | * | ||
373 | * This function performs the generic NAND bad block marking steps (i.e., bad | ||
374 | * block table(s) and/or marker(s)). We only allow the hardware driver to | ||
375 | * specify how to write bad block markers to OOB (chip->block_markbad). | ||
376 | * | ||
377 | * We try operations in the following order: | ||
345 | * (1) erase the affected block, to allow OOB marker to be written cleanly | 378 | * (1) erase the affected block, to allow OOB marker to be written cleanly |
346 | * (2) update in-memory BBT | 379 | * (2) write bad block marker to OOB area of affected block (unless flag |
347 | * (3) write bad block marker to OOB area of affected block | 380 | * NAND_BBT_NO_OOB_BBM is present) |
348 | * (4) update flash-based BBT | 381 | * (3) update the BBT |
349 | * Note that we retain the first error encountered in (3) or (4), finish the | 382 | * Note that we retain the first error encountered in (2) or (3), finish the |
350 | * procedures, and dump the error in the end. | 383 | * procedures, and dump the error in the end. |
351 | */ | 384 | */ |
352 | static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) | 385 | static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs) |
353 | { | 386 | { |
354 | struct nand_chip *chip = mtd->priv; | 387 | struct nand_chip *chip = mtd->priv; |
355 | uint8_t buf[2] = { 0, 0 }; | 388 | int res, ret = 0; |
356 | int block, res, ret = 0, i = 0; | ||
357 | int write_oob = !(chip->bbt_options & NAND_BBT_NO_OOB_BBM); | ||
358 | 389 | ||
359 | if (write_oob) { | 390 | if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) { |
360 | struct erase_info einfo; | 391 | struct erase_info einfo; |
361 | 392 | ||
362 | /* Attempt erase before marking OOB */ | 393 | /* Attempt erase before marking OOB */ |
363 | memset(&einfo, 0, sizeof(einfo)); | 394 | memset(&einfo, 0, sizeof(einfo)); |
364 | einfo.mtd = mtd; | 395 | einfo.mtd = mtd; |
365 | einfo.addr = ofs; | 396 | einfo.addr = ofs; |
366 | einfo.len = 1 << chip->phys_erase_shift; | 397 | einfo.len = 1ULL << chip->phys_erase_shift; |
367 | nand_erase_nand(mtd, &einfo, 0); | 398 | nand_erase_nand(mtd, &einfo, 0); |
368 | } | ||
369 | |||
370 | /* Get block number */ | ||
371 | block = (int)(ofs >> chip->bbt_erase_shift); | ||
372 | /* Mark block bad in memory-based BBT */ | ||
373 | if (chip->bbt) | ||
374 | chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); | ||
375 | |||
376 | /* Write bad block marker to OOB */ | ||
377 | if (write_oob) { | ||
378 | struct mtd_oob_ops ops; | ||
379 | loff_t wr_ofs = ofs; | ||
380 | 399 | ||
400 | /* Write bad block marker to OOB */ | ||
381 | nand_get_device(mtd, FL_WRITING); | 401 | nand_get_device(mtd, FL_WRITING); |
382 | 402 | ret = chip->block_markbad(mtd, ofs); | |
383 | ops.datbuf = NULL; | ||
384 | ops.oobbuf = buf; | ||
385 | ops.ooboffs = chip->badblockpos; | ||
386 | if (chip->options & NAND_BUSWIDTH_16) { | ||
387 | ops.ooboffs &= ~0x01; | ||
388 | ops.len = ops.ooblen = 2; | ||
389 | } else { | ||
390 | ops.len = ops.ooblen = 1; | ||
391 | } | ||
392 | ops.mode = MTD_OPS_PLACE_OOB; | ||
393 | |||
394 | /* Write to first/last page(s) if necessary */ | ||
395 | if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) | ||
396 | wr_ofs += mtd->erasesize - mtd->writesize; | ||
397 | do { | ||
398 | res = nand_do_write_oob(mtd, wr_ofs, &ops); | ||
399 | if (!ret) | ||
400 | ret = res; | ||
401 | |||
402 | i++; | ||
403 | wr_ofs += mtd->writesize; | ||
404 | } while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2); | ||
405 | |||
406 | nand_release_device(mtd); | 403 | nand_release_device(mtd); |
407 | } | 404 | } |
408 | 405 | ||
409 | /* Update flash-based bad block table */ | 406 | /* Mark block bad in BBT */ |
410 | if (chip->bbt_options & NAND_BBT_USE_FLASH) { | 407 | if (chip->bbt) { |
411 | res = nand_update_bbt(mtd, ofs); | 408 | res = nand_markbad_bbt(mtd, ofs); |
412 | if (!ret) | 409 | if (!ret) |
413 | ret = res; | 410 | ret = res; |
414 | } | 411 | } |
@@ -1983,13 +1980,14 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1983 | * nand_write_subpage_hwecc - [REPLACABLE] hardware ECC based subpage write | 1980 | * nand_write_subpage_hwecc - [REPLACABLE] hardware ECC based subpage write |
1984 | * @mtd: mtd info structure | 1981 | * @mtd: mtd info structure |
1985 | * @chip: nand chip info structure | 1982 | * @chip: nand chip info structure |
1986 | * @column: column address of subpage within the page | 1983 | * @offset: column address of subpage within the page |
1987 | * @data_len: data length | 1984 | * @data_len: data length |
1985 | * @buf: data buffer | ||
1988 | * @oob_required: must write chip->oob_poi to OOB | 1986 | * @oob_required: must write chip->oob_poi to OOB |
1989 | */ | 1987 | */ |
1990 | static int nand_write_subpage_hwecc(struct mtd_info *mtd, | 1988 | static int nand_write_subpage_hwecc(struct mtd_info *mtd, |
1991 | struct nand_chip *chip, uint32_t offset, | 1989 | struct nand_chip *chip, uint32_t offset, |
1992 | uint32_t data_len, const uint8_t *data_buf, | 1990 | uint32_t data_len, const uint8_t *buf, |
1993 | int oob_required) | 1991 | int oob_required) |
1994 | { | 1992 | { |
1995 | uint8_t *oob_buf = chip->oob_poi; | 1993 | uint8_t *oob_buf = chip->oob_poi; |
@@ -2008,20 +2006,20 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd, | |||
2008 | chip->ecc.hwctl(mtd, NAND_ECC_WRITE); | 2006 | chip->ecc.hwctl(mtd, NAND_ECC_WRITE); |
2009 | 2007 | ||
2010 | /* write data (untouched subpages already masked by 0xFF) */ | 2008 | /* write data (untouched subpages already masked by 0xFF) */ |
2011 | chip->write_buf(mtd, data_buf, ecc_size); | 2009 | chip->write_buf(mtd, buf, ecc_size); |
2012 | 2010 | ||
2013 | /* mask ECC of un-touched subpages by padding 0xFF */ | 2011 | /* mask ECC of un-touched subpages by padding 0xFF */ |
2014 | if ((step < start_step) || (step > end_step)) | 2012 | if ((step < start_step) || (step > end_step)) |
2015 | memset(ecc_calc, 0xff, ecc_bytes); | 2013 | memset(ecc_calc, 0xff, ecc_bytes); |
2016 | else | 2014 | else |
2017 | chip->ecc.calculate(mtd, data_buf, ecc_calc); | 2015 | chip->ecc.calculate(mtd, buf, ecc_calc); |
2018 | 2016 | ||
2019 | /* mask OOB of un-touched subpages by padding 0xFF */ | 2017 | /* mask OOB of un-touched subpages by padding 0xFF */ |
2020 | /* if oob_required, preserve OOB metadata of written subpage */ | 2018 | /* if oob_required, preserve OOB metadata of written subpage */ |
2021 | if (!oob_required || (step < start_step) || (step > end_step)) | 2019 | if (!oob_required || (step < start_step) || (step > end_step)) |
2022 | memset(oob_buf, 0xff, oob_bytes); | 2020 | memset(oob_buf, 0xff, oob_bytes); |
2023 | 2021 | ||
2024 | data_buf += ecc_size; | 2022 | buf += ecc_size; |
2025 | ecc_calc += ecc_bytes; | 2023 | ecc_calc += ecc_bytes; |
2026 | oob_buf += oob_bytes; | 2024 | oob_buf += oob_bytes; |
2027 | } | 2025 | } |
@@ -2633,7 +2631,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | |||
2633 | } | 2631 | } |
2634 | 2632 | ||
2635 | /* Increment page address and decrement length */ | 2633 | /* Increment page address and decrement length */ |
2636 | len -= (1 << chip->phys_erase_shift); | 2634 | len -= (1ULL << chip->phys_erase_shift); |
2637 | page += pages_per_block; | 2635 | page += pages_per_block; |
2638 | 2636 | ||
2639 | /* Check, if we cross a chip boundary */ | 2637 | /* Check, if we cross a chip boundary */ |
@@ -2694,7 +2692,6 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs) | |||
2694 | */ | 2692 | */ |
2695 | static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) | 2693 | static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) |
2696 | { | 2694 | { |
2697 | struct nand_chip *chip = mtd->priv; | ||
2698 | int ret; | 2695 | int ret; |
2699 | 2696 | ||
2700 | ret = nand_block_isbad(mtd, ofs); | 2697 | ret = nand_block_isbad(mtd, ofs); |
@@ -2705,7 +2702,7 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
2705 | return ret; | 2702 | return ret; |
2706 | } | 2703 | } |
2707 | 2704 | ||
2708 | return chip->block_markbad(mtd, ofs); | 2705 | return nand_block_markbad_lowlevel(mtd, ofs); |
2709 | } | 2706 | } |
2710 | 2707 | ||
2711 | /** | 2708 | /** |
@@ -2720,7 +2717,9 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip, | |||
2720 | { | 2717 | { |
2721 | int status; | 2718 | int status; |
2722 | 2719 | ||
2723 | if (!chip->onfi_version) | 2720 | if (!chip->onfi_version || |
2721 | !(le16_to_cpu(chip->onfi_params.opt_cmd) | ||
2722 | & ONFI_OPT_CMD_SET_GET_FEATURES)) | ||
2724 | return -EINVAL; | 2723 | return -EINVAL; |
2725 | 2724 | ||
2726 | chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1); | 2725 | chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1); |
@@ -2741,7 +2740,9 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip, | |||
2741 | static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip, | 2740 | static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip, |
2742 | int addr, uint8_t *subfeature_param) | 2741 | int addr, uint8_t *subfeature_param) |
2743 | { | 2742 | { |
2744 | if (!chip->onfi_version) | 2743 | if (!chip->onfi_version || |
2744 | !(le16_to_cpu(chip->onfi_params.opt_cmd) | ||
2745 | & ONFI_OPT_CMD_SET_GET_FEATURES)) | ||
2745 | return -EINVAL; | 2746 | return -EINVAL; |
2746 | 2747 | ||
2747 | /* clear the sub feature parameters */ | 2748 | /* clear the sub feature parameters */ |
@@ -2793,7 +2794,15 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) | |||
2793 | 2794 | ||
2794 | if (!chip->select_chip) | 2795 | if (!chip->select_chip) |
2795 | chip->select_chip = nand_select_chip; | 2796 | chip->select_chip = nand_select_chip; |
2796 | if (!chip->read_byte) | 2797 | |
2798 | /* set for ONFI nand */ | ||
2799 | if (!chip->onfi_set_features) | ||
2800 | chip->onfi_set_features = nand_onfi_set_features; | ||
2801 | if (!chip->onfi_get_features) | ||
2802 | chip->onfi_get_features = nand_onfi_get_features; | ||
2803 | |||
2804 | /* If called twice, pointers that depend on busw may need to be reset */ | ||
2805 | if (!chip->read_byte || chip->read_byte == nand_read_byte) | ||
2797 | chip->read_byte = busw ? nand_read_byte16 : nand_read_byte; | 2806 | chip->read_byte = busw ? nand_read_byte16 : nand_read_byte; |
2798 | if (!chip->read_word) | 2807 | if (!chip->read_word) |
2799 | chip->read_word = nand_read_word; | 2808 | chip->read_word = nand_read_word; |
@@ -2801,9 +2810,9 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) | |||
2801 | chip->block_bad = nand_block_bad; | 2810 | chip->block_bad = nand_block_bad; |
2802 | if (!chip->block_markbad) | 2811 | if (!chip->block_markbad) |
2803 | chip->block_markbad = nand_default_block_markbad; | 2812 | chip->block_markbad = nand_default_block_markbad; |
2804 | if (!chip->write_buf) | 2813 | if (!chip->write_buf || chip->write_buf == nand_write_buf) |
2805 | chip->write_buf = busw ? nand_write_buf16 : nand_write_buf; | 2814 | chip->write_buf = busw ? nand_write_buf16 : nand_write_buf; |
2806 | if (!chip->read_buf) | 2815 | if (!chip->read_buf || chip->read_buf == nand_read_buf) |
2807 | chip->read_buf = busw ? nand_read_buf16 : nand_read_buf; | 2816 | chip->read_buf = busw ? nand_read_buf16 : nand_read_buf; |
2808 | if (!chip->scan_bbt) | 2817 | if (!chip->scan_bbt) |
2809 | chip->scan_bbt = nand_default_bbt; | 2818 | chip->scan_bbt = nand_default_bbt; |
@@ -2846,6 +2855,78 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len) | |||
2846 | return crc; | 2855 | return crc; |
2847 | } | 2856 | } |
2848 | 2857 | ||
2858 | /* Parse the Extended Parameter Page. */ | ||
2859 | static int nand_flash_detect_ext_param_page(struct mtd_info *mtd, | ||
2860 | struct nand_chip *chip, struct nand_onfi_params *p) | ||
2861 | { | ||
2862 | struct onfi_ext_param_page *ep; | ||
2863 | struct onfi_ext_section *s; | ||
2864 | struct onfi_ext_ecc_info *ecc; | ||
2865 | uint8_t *cursor; | ||
2866 | int ret = -EINVAL; | ||
2867 | int len; | ||
2868 | int i; | ||
2869 | |||
2870 | len = le16_to_cpu(p->ext_param_page_length) * 16; | ||
2871 | ep = kmalloc(len, GFP_KERNEL); | ||
2872 | if (!ep) { | ||
2873 | ret = -ENOMEM; | ||
2874 | goto ext_out; | ||
2875 | } | ||
2876 | |||
2877 | /* Send our own NAND_CMD_PARAM. */ | ||
2878 | chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1); | ||
2879 | |||
2880 | /* Use the Change Read Column command to skip the ONFI param pages. */ | ||
2881 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, | ||
2882 | sizeof(*p) * p->num_of_param_pages , -1); | ||
2883 | |||
2884 | /* Read out the Extended Parameter Page. */ | ||
2885 | chip->read_buf(mtd, (uint8_t *)ep, len); | ||
2886 | if ((onfi_crc16(ONFI_CRC_BASE, ((uint8_t *)ep) + 2, len - 2) | ||
2887 | != le16_to_cpu(ep->crc))) { | ||
2888 | pr_debug("fail in the CRC.\n"); | ||
2889 | goto ext_out; | ||
2890 | } | ||
2891 | |||
2892 | /* | ||
2893 | * Check the signature. | ||
2894 | * Do not strictly follow the ONFI spec, maybe changed in future. | ||
2895 | */ | ||
2896 | if (strncmp(ep->sig, "EPPS", 4)) { | ||
2897 | pr_debug("The signature is invalid.\n"); | ||
2898 | goto ext_out; | ||
2899 | } | ||
2900 | |||
2901 | /* find the ECC section. */ | ||
2902 | cursor = (uint8_t *)(ep + 1); | ||
2903 | for (i = 0; i < ONFI_EXT_SECTION_MAX; i++) { | ||
2904 | s = ep->sections + i; | ||
2905 | if (s->type == ONFI_SECTION_TYPE_2) | ||
2906 | break; | ||
2907 | cursor += s->length * 16; | ||
2908 | } | ||
2909 | if (i == ONFI_EXT_SECTION_MAX) { | ||
2910 | pr_debug("We can not find the ECC section.\n"); | ||
2911 | goto ext_out; | ||
2912 | } | ||
2913 | |||
2914 | /* get the info we want. */ | ||
2915 | ecc = (struct onfi_ext_ecc_info *)cursor; | ||
2916 | |||
2917 | if (ecc->codeword_size) { | ||
2918 | chip->ecc_strength_ds = ecc->ecc_bits; | ||
2919 | chip->ecc_step_ds = 1 << ecc->codeword_size; | ||
2920 | } | ||
2921 | |||
2922 | pr_info("ONFI extended param page detected.\n"); | ||
2923 | return 0; | ||
2924 | |||
2925 | ext_out: | ||
2926 | kfree(ep); | ||
2927 | return ret; | ||
2928 | } | ||
2929 | |||
2849 | /* | 2930 | /* |
2850 | * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise. | 2931 | * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise. |
2851 | */ | 2932 | */ |
@@ -2907,9 +2988,31 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, | |||
2907 | mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); | 2988 | mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); |
2908 | chip->chipsize = le32_to_cpu(p->blocks_per_lun); | 2989 | chip->chipsize = le32_to_cpu(p->blocks_per_lun); |
2909 | chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count; | 2990 | chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count; |
2910 | *busw = 0; | 2991 | |
2911 | if (le16_to_cpu(p->features) & 1) | 2992 | if (onfi_feature(chip) & ONFI_FEATURE_16_BIT_BUS) |
2912 | *busw = NAND_BUSWIDTH_16; | 2993 | *busw = NAND_BUSWIDTH_16; |
2994 | else | ||
2995 | *busw = 0; | ||
2996 | |||
2997 | if (p->ecc_bits != 0xff) { | ||
2998 | chip->ecc_strength_ds = p->ecc_bits; | ||
2999 | chip->ecc_step_ds = 512; | ||
3000 | } else if (chip->onfi_version >= 21 && | ||
3001 | (onfi_feature(chip) & ONFI_FEATURE_EXT_PARAM_PAGE)) { | ||
3002 | |||
3003 | /* | ||
3004 | * The nand_flash_detect_ext_param_page() uses the | ||
3005 | * Change Read Column command which maybe not supported | ||
3006 | * by the chip->cmdfunc. So try to update the chip->cmdfunc | ||
3007 | * now. We do not replace user supplied command function. | ||
3008 | */ | ||
3009 | if (mtd->writesize > 512 && chip->cmdfunc == nand_command) | ||
3010 | chip->cmdfunc = nand_command_lp; | ||
3011 | |||
3012 | /* The Extended Parameter Page is supported since ONFI 2.1. */ | ||
3013 | if (nand_flash_detect_ext_param_page(mtd, chip, p)) | ||
3014 | pr_info("Failed to detect the extended param page.\n"); | ||
3015 | } | ||
2913 | 3016 | ||
2914 | pr_info("ONFI flash detected\n"); | 3017 | pr_info("ONFI flash detected\n"); |
2915 | return 1; | 3018 | return 1; |
@@ -3086,6 +3189,22 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, | |||
3086 | extid >>= 2; | 3189 | extid >>= 2; |
3087 | /* Get buswidth information */ | 3190 | /* Get buswidth information */ |
3088 | *busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; | 3191 | *busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; |
3192 | |||
3193 | /* | ||
3194 | * Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per | ||
3195 | * 512B page. For Toshiba SLC, we decode the 5th/6th byte as | ||
3196 | * follows: | ||
3197 | * - ID byte 6, bits[2:0]: 100b -> 43nm, 101b -> 32nm, | ||
3198 | * 110b -> 24nm | ||
3199 | * - ID byte 5, bit[7]: 1 -> BENAND, 0 -> raw SLC | ||
3200 | */ | ||
3201 | if (id_len >= 6 && id_data[0] == NAND_MFR_TOSHIBA && | ||
3202 | !(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && | ||
3203 | (id_data[5] & 0x7) == 0x6 /* 24nm */ && | ||
3204 | !(id_data[4] & 0x80) /* !BENAND */) { | ||
3205 | mtd->oobsize = 32 * mtd->writesize >> 9; | ||
3206 | } | ||
3207 | |||
3089 | } | 3208 | } |
3090 | } | 3209 | } |
3091 | 3210 | ||
@@ -3172,6 +3291,8 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip, | |||
3172 | chip->cellinfo = id_data[2]; | 3291 | chip->cellinfo = id_data[2]; |
3173 | chip->chipsize = (uint64_t)type->chipsize << 20; | 3292 | chip->chipsize = (uint64_t)type->chipsize << 20; |
3174 | chip->options |= type->options; | 3293 | chip->options |= type->options; |
3294 | chip->ecc_strength_ds = NAND_ECC_STRENGTH(type); | ||
3295 | chip->ecc_step_ds = NAND_ECC_STEP(type); | ||
3175 | 3296 | ||
3176 | *busw = type->options & NAND_BUSWIDTH_16; | 3297 | *busw = type->options & NAND_BUSWIDTH_16; |
3177 | 3298 | ||
@@ -3446,12 +3567,6 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3446 | if (!chip->write_page) | 3567 | if (!chip->write_page) |
3447 | chip->write_page = nand_write_page; | 3568 | chip->write_page = nand_write_page; |
3448 | 3569 | ||
3449 | /* set for ONFI nand */ | ||
3450 | if (!chip->onfi_set_features) | ||
3451 | chip->onfi_set_features = nand_onfi_set_features; | ||
3452 | if (!chip->onfi_get_features) | ||
3453 | chip->onfi_get_features = nand_onfi_get_features; | ||
3454 | |||
3455 | /* | 3570 | /* |
3456 | * Check ECC mode, default to software if 3byte/512byte hardware ECC is | 3571 | * Check ECC mode, default to software if 3byte/512byte hardware ECC is |
3457 | * selected and we have 256 byte pagesize fallback to software ECC | 3572 | * selected and we have 256 byte pagesize fallback to software ECC |
@@ -3674,6 +3789,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3674 | /* propagate ecc info to mtd_info */ | 3789 | /* propagate ecc info to mtd_info */ |
3675 | mtd->ecclayout = chip->ecc.layout; | 3790 | mtd->ecclayout = chip->ecc.layout; |
3676 | mtd->ecc_strength = chip->ecc.strength; | 3791 | mtd->ecc_strength = chip->ecc.strength; |
3792 | mtd->ecc_step_size = chip->ecc.size; | ||
3677 | /* | 3793 | /* |
3678 | * Initialize bitflip_threshold to its default prior scan_bbt() call. | 3794 | * Initialize bitflip_threshold to its default prior scan_bbt() call. |
3679 | * scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be | 3795 | * scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be |
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 267264320e06..bc06196d5739 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c | |||
@@ -71,6 +71,30 @@ | |||
71 | #include <linux/export.h> | 71 | #include <linux/export.h> |
72 | #include <linux/string.h> | 72 | #include <linux/string.h> |
73 | 73 | ||
74 | #define BBT_BLOCK_GOOD 0x00 | ||
75 | #define BBT_BLOCK_WORN 0x01 | ||
76 | #define BBT_BLOCK_RESERVED 0x02 | ||
77 | #define BBT_BLOCK_FACTORY_BAD 0x03 | ||
78 | |||
79 | #define BBT_ENTRY_MASK 0x03 | ||
80 | #define BBT_ENTRY_SHIFT 2 | ||
81 | |||
82 | static int nand_update_bbt(struct mtd_info *mtd, loff_t offs); | ||
83 | |||
84 | static inline uint8_t bbt_get_entry(struct nand_chip *chip, int block) | ||
85 | { | ||
86 | uint8_t entry = chip->bbt[block >> BBT_ENTRY_SHIFT]; | ||
87 | entry >>= (block & BBT_ENTRY_MASK) * 2; | ||
88 | return entry & BBT_ENTRY_MASK; | ||
89 | } | ||
90 | |||
91 | static inline void bbt_mark_entry(struct nand_chip *chip, int block, | ||
92 | uint8_t mark) | ||
93 | { | ||
94 | uint8_t msk = (mark & BBT_ENTRY_MASK) << ((block & BBT_ENTRY_MASK) * 2); | ||
95 | chip->bbt[block >> BBT_ENTRY_SHIFT] |= msk; | ||
96 | } | ||
97 | |||
74 | static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td) | 98 | static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td) |
75 | { | 99 | { |
76 | if (memcmp(buf, td->pattern, td->len)) | 100 | if (memcmp(buf, td->pattern, td->len)) |
@@ -86,33 +110,17 @@ static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td) | |||
86 | * @td: search pattern descriptor | 110 | * @td: search pattern descriptor |
87 | * | 111 | * |
88 | * Check for a pattern at the given place. Used to search bad block tables and | 112 | * Check for a pattern at the given place. Used to search bad block tables and |
89 | * good / bad block identifiers. If the SCAN_EMPTY option is set then check, if | 113 | * good / bad block identifiers. |
90 | * all bytes except the pattern area contain 0xff. | ||
91 | */ | 114 | */ |
92 | static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td) | 115 | static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td) |
93 | { | 116 | { |
94 | int end = 0; | ||
95 | uint8_t *p = buf; | ||
96 | |||
97 | if (td->options & NAND_BBT_NO_OOB) | 117 | if (td->options & NAND_BBT_NO_OOB) |
98 | return check_pattern_no_oob(buf, td); | 118 | return check_pattern_no_oob(buf, td); |
99 | 119 | ||
100 | end = paglen + td->offs; | ||
101 | if (td->options & NAND_BBT_SCANEMPTY) | ||
102 | if (memchr_inv(p, 0xff, end)) | ||
103 | return -1; | ||
104 | p += end; | ||
105 | |||
106 | /* Compare the pattern */ | 120 | /* Compare the pattern */ |
107 | if (memcmp(p, td->pattern, td->len)) | 121 | if (memcmp(buf + paglen + td->offs, td->pattern, td->len)) |
108 | return -1; | 122 | return -1; |
109 | 123 | ||
110 | if (td->options & NAND_BBT_SCANEMPTY) { | ||
111 | p += td->len; | ||
112 | end += td->len; | ||
113 | if (memchr_inv(p, 0xff, len - end)) | ||
114 | return -1; | ||
115 | } | ||
116 | return 0; | 124 | return 0; |
117 | } | 125 | } |
118 | 126 | ||
@@ -159,7 +167,7 @@ static u32 add_marker_len(struct nand_bbt_descr *td) | |||
159 | * @page: the starting page | 167 | * @page: the starting page |
160 | * @num: the number of bbt descriptors to read | 168 | * @num: the number of bbt descriptors to read |
161 | * @td: the bbt describtion table | 169 | * @td: the bbt describtion table |
162 | * @offs: offset in the memory table | 170 | * @offs: block number offset in the table |
163 | * | 171 | * |
164 | * Read the bad block table starting from page. | 172 | * Read the bad block table starting from page. |
165 | */ | 173 | */ |
@@ -209,14 +217,16 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, | |||
209 | /* Analyse data */ | 217 | /* Analyse data */ |
210 | for (i = 0; i < len; i++) { | 218 | for (i = 0; i < len; i++) { |
211 | uint8_t dat = buf[i]; | 219 | uint8_t dat = buf[i]; |
212 | for (j = 0; j < 8; j += bits, act += 2) { | 220 | for (j = 0; j < 8; j += bits, act++) { |
213 | uint8_t tmp = (dat >> j) & msk; | 221 | uint8_t tmp = (dat >> j) & msk; |
214 | if (tmp == msk) | 222 | if (tmp == msk) |
215 | continue; | 223 | continue; |
216 | if (reserved_block_code && (tmp == reserved_block_code)) { | 224 | if (reserved_block_code && (tmp == reserved_block_code)) { |
217 | pr_info("nand_read_bbt: reserved block at 0x%012llx\n", | 225 | pr_info("nand_read_bbt: reserved block at 0x%012llx\n", |
218 | (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift); | 226 | (loff_t)(offs + act) << |
219 | this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06); | 227 | this->bbt_erase_shift); |
228 | bbt_mark_entry(this, offs + act, | ||
229 | BBT_BLOCK_RESERVED); | ||
220 | mtd->ecc_stats.bbtblocks++; | 230 | mtd->ecc_stats.bbtblocks++; |
221 | continue; | 231 | continue; |
222 | } | 232 | } |
@@ -225,12 +235,15 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, | |||
225 | * move this message to pr_debug. | 235 | * move this message to pr_debug. |
226 | */ | 236 | */ |
227 | pr_info("nand_read_bbt: bad block at 0x%012llx\n", | 237 | pr_info("nand_read_bbt: bad block at 0x%012llx\n", |
228 | (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift); | 238 | (loff_t)(offs + act) << |
239 | this->bbt_erase_shift); | ||
229 | /* Factory marked bad or worn out? */ | 240 | /* Factory marked bad or worn out? */ |
230 | if (tmp == 0) | 241 | if (tmp == 0) |
231 | this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06); | 242 | bbt_mark_entry(this, offs + act, |
243 | BBT_BLOCK_FACTORY_BAD); | ||
232 | else | 244 | else |
233 | this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06); | 245 | bbt_mark_entry(this, offs + act, |
246 | BBT_BLOCK_WORN); | ||
234 | mtd->ecc_stats.badblocks++; | 247 | mtd->ecc_stats.badblocks++; |
235 | } | 248 | } |
236 | } | 249 | } |
@@ -265,7 +278,7 @@ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc | |||
265 | td, offs); | 278 | td, offs); |
266 | if (res) | 279 | if (res) |
267 | return res; | 280 | return res; |
268 | offs += this->chipsize >> (this->bbt_erase_shift + 2); | 281 | offs += this->chipsize >> this->bbt_erase_shift; |
269 | } | 282 | } |
270 | } else { | 283 | } else { |
271 | res = read_bbt(mtd, buf, td->pages[0], | 284 | res = read_bbt(mtd, buf, td->pages[0], |
@@ -478,22 +491,12 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
478 | else | 491 | else |
479 | numpages = 1; | 492 | numpages = 1; |
480 | 493 | ||
481 | if (!(bd->options & NAND_BBT_SCANEMPTY)) { | 494 | /* We need only read few bytes from the OOB area */ |
482 | /* We need only read few bytes from the OOB area */ | 495 | scanlen = 0; |
483 | scanlen = 0; | 496 | readlen = bd->len; |
484 | readlen = bd->len; | ||
485 | } else { | ||
486 | /* Full page content should be read */ | ||
487 | scanlen = mtd->writesize + mtd->oobsize; | ||
488 | readlen = numpages * mtd->writesize; | ||
489 | } | ||
490 | 497 | ||
491 | if (chip == -1) { | 498 | if (chip == -1) { |
492 | /* | 499 | numblocks = mtd->size >> this->bbt_erase_shift; |
493 | * Note that numblocks is 2 * (real numblocks) here, see i+=2 | ||
494 | * below as it makes shifting and masking less painful | ||
495 | */ | ||
496 | numblocks = mtd->size >> (this->bbt_erase_shift - 1); | ||
497 | startblock = 0; | 500 | startblock = 0; |
498 | from = 0; | 501 | from = 0; |
499 | } else { | 502 | } else { |
@@ -502,16 +505,16 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
502 | chip + 1, this->numchips); | 505 | chip + 1, this->numchips); |
503 | return -EINVAL; | 506 | return -EINVAL; |
504 | } | 507 | } |
505 | numblocks = this->chipsize >> (this->bbt_erase_shift - 1); | 508 | numblocks = this->chipsize >> this->bbt_erase_shift; |
506 | startblock = chip * numblocks; | 509 | startblock = chip * numblocks; |
507 | numblocks += startblock; | 510 | numblocks += startblock; |
508 | from = (loff_t)startblock << (this->bbt_erase_shift - 1); | 511 | from = (loff_t)startblock << this->bbt_erase_shift; |
509 | } | 512 | } |
510 | 513 | ||
511 | if (this->bbt_options & NAND_BBT_SCANLASTPAGE) | 514 | if (this->bbt_options & NAND_BBT_SCANLASTPAGE) |
512 | from += mtd->erasesize - (mtd->writesize * numpages); | 515 | from += mtd->erasesize - (mtd->writesize * numpages); |
513 | 516 | ||
514 | for (i = startblock; i < numblocks;) { | 517 | for (i = startblock; i < numblocks; i++) { |
515 | int ret; | 518 | int ret; |
516 | 519 | ||
517 | BUG_ON(bd->options & NAND_BBT_NO_OOB); | 520 | BUG_ON(bd->options & NAND_BBT_NO_OOB); |
@@ -526,13 +529,12 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
526 | return ret; | 529 | return ret; |
527 | 530 | ||
528 | if (ret) { | 531 | if (ret) { |
529 | this->bbt[i >> 3] |= 0x03 << (i & 0x6); | 532 | bbt_mark_entry(this, i, BBT_BLOCK_FACTORY_BAD); |
530 | pr_warn("Bad eraseblock %d at 0x%012llx\n", | 533 | pr_warn("Bad eraseblock %d at 0x%012llx\n", |
531 | i >> 1, (unsigned long long)from); | 534 | i, (unsigned long long)from); |
532 | mtd->ecc_stats.badblocks++; | 535 | mtd->ecc_stats.badblocks++; |
533 | } | 536 | } |
534 | 537 | ||
535 | i += 2; | ||
536 | from += (1 << this->bbt_erase_shift); | 538 | from += (1 << this->bbt_erase_shift); |
537 | } | 539 | } |
538 | return 0; | 540 | return 0; |
@@ -655,9 +657,9 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
655 | { | 657 | { |
656 | struct nand_chip *this = mtd->priv; | 658 | struct nand_chip *this = mtd->priv; |
657 | struct erase_info einfo; | 659 | struct erase_info einfo; |
658 | int i, j, res, chip = 0; | 660 | int i, res, chip = 0; |
659 | int bits, startblock, dir, page, offs, numblocks, sft, sftmsk; | 661 | int bits, startblock, dir, page, offs, numblocks, sft, sftmsk; |
660 | int nrchips, bbtoffs, pageoffs, ooboffs; | 662 | int nrchips, pageoffs, ooboffs; |
661 | uint8_t msk[4]; | 663 | uint8_t msk[4]; |
662 | uint8_t rcode = td->reserved_block_code; | 664 | uint8_t rcode = td->reserved_block_code; |
663 | size_t retlen, len = 0; | 665 | size_t retlen, len = 0; |
@@ -713,10 +715,9 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
713 | for (i = 0; i < td->maxblocks; i++) { | 715 | for (i = 0; i < td->maxblocks; i++) { |
714 | int block = startblock + dir * i; | 716 | int block = startblock + dir * i; |
715 | /* Check, if the block is bad */ | 717 | /* Check, if the block is bad */ |
716 | switch ((this->bbt[block >> 2] >> | 718 | switch (bbt_get_entry(this, block)) { |
717 | (2 * (block & 0x03))) & 0x03) { | 719 | case BBT_BLOCK_WORN: |
718 | case 0x01: | 720 | case BBT_BLOCK_FACTORY_BAD: |
719 | case 0x03: | ||
720 | continue; | 721 | continue; |
721 | } | 722 | } |
722 | page = block << | 723 | page = block << |
@@ -748,8 +749,6 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
748 | default: return -EINVAL; | 749 | default: return -EINVAL; |
749 | } | 750 | } |
750 | 751 | ||
751 | bbtoffs = chip * (numblocks >> 2); | ||
752 | |||
753 | to = ((loff_t)page) << this->page_shift; | 752 | to = ((loff_t)page) << this->page_shift; |
754 | 753 | ||
755 | /* Must we save the block contents? */ | 754 | /* Must we save the block contents? */ |
@@ -814,16 +813,12 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
814 | buf[ooboffs + td->veroffs] = td->version[chip]; | 813 | buf[ooboffs + td->veroffs] = td->version[chip]; |
815 | 814 | ||
816 | /* Walk through the memory table */ | 815 | /* Walk through the memory table */ |
817 | for (i = 0; i < numblocks;) { | 816 | for (i = 0; i < numblocks; i++) { |
818 | uint8_t dat; | 817 | uint8_t dat; |
819 | dat = this->bbt[bbtoffs + (i >> 2)]; | 818 | int sftcnt = (i << (3 - sft)) & sftmsk; |
820 | for (j = 0; j < 4; j++, i++) { | 819 | dat = bbt_get_entry(this, chip * numblocks + i); |
821 | int sftcnt = (i << (3 - sft)) & sftmsk; | 820 | /* Do not store the reserved bbt blocks! */ |
822 | /* Do not store the reserved bbt blocks! */ | 821 | buf[offs + (i >> sft)] &= ~(msk[dat] << sftcnt); |
823 | buf[offs + (i >> sft)] &= | ||
824 | ~(msk[dat & 0x03] << sftcnt); | ||
825 | dat >>= 2; | ||
826 | } | ||
827 | } | 822 | } |
828 | 823 | ||
829 | memset(&einfo, 0, sizeof(einfo)); | 824 | memset(&einfo, 0, sizeof(einfo)); |
@@ -865,7 +860,6 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b | |||
865 | { | 860 | { |
866 | struct nand_chip *this = mtd->priv; | 861 | struct nand_chip *this = mtd->priv; |
867 | 862 | ||
868 | bd->options &= ~NAND_BBT_SCANEMPTY; | ||
869 | return create_bbt(mtd, this->buffers->databuf, bd, -1); | 863 | return create_bbt(mtd, this->buffers->databuf, bd, -1); |
870 | } | 864 | } |
871 | 865 | ||
@@ -1009,7 +1003,7 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) | |||
1009 | { | 1003 | { |
1010 | struct nand_chip *this = mtd->priv; | 1004 | struct nand_chip *this = mtd->priv; |
1011 | int i, j, chips, block, nrblocks, update; | 1005 | int i, j, chips, block, nrblocks, update; |
1012 | uint8_t oldval, newval; | 1006 | uint8_t oldval; |
1013 | 1007 | ||
1014 | /* Do we have a bbt per chip? */ | 1008 | /* Do we have a bbt per chip? */ |
1015 | if (td->options & NAND_BBT_PERCHIP) { | 1009 | if (td->options & NAND_BBT_PERCHIP) { |
@@ -1026,12 +1020,12 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) | |||
1026 | if (td->pages[i] == -1) | 1020 | if (td->pages[i] == -1) |
1027 | continue; | 1021 | continue; |
1028 | block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift); | 1022 | block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift); |
1029 | block <<= 1; | 1023 | oldval = bbt_get_entry(this, block); |
1030 | oldval = this->bbt[(block >> 3)]; | 1024 | bbt_mark_entry(this, block, BBT_BLOCK_RESERVED); |
1031 | newval = oldval | (0x2 << (block & 0x06)); | 1025 | if ((oldval != BBT_BLOCK_RESERVED) && |
1032 | this->bbt[(block >> 3)] = newval; | 1026 | td->reserved_block_code) |
1033 | if ((oldval != newval) && td->reserved_block_code) | 1027 | nand_update_bbt(mtd, (loff_t)block << |
1034 | nand_update_bbt(mtd, (loff_t)block << (this->bbt_erase_shift - 1)); | 1028 | this->bbt_erase_shift); |
1035 | continue; | 1029 | continue; |
1036 | } | 1030 | } |
1037 | update = 0; | 1031 | update = 0; |
@@ -1039,14 +1033,12 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) | |||
1039 | block = ((i + 1) * nrblocks) - td->maxblocks; | 1033 | block = ((i + 1) * nrblocks) - td->maxblocks; |
1040 | else | 1034 | else |
1041 | block = i * nrblocks; | 1035 | block = i * nrblocks; |
1042 | block <<= 1; | ||
1043 | for (j = 0; j < td->maxblocks; j++) { | 1036 | for (j = 0; j < td->maxblocks; j++) { |
1044 | oldval = this->bbt[(block >> 3)]; | 1037 | oldval = bbt_get_entry(this, block); |
1045 | newval = oldval | (0x2 << (block & 0x06)); | 1038 | bbt_mark_entry(this, block, BBT_BLOCK_RESERVED); |
1046 | this->bbt[(block >> 3)] = newval; | 1039 | if (oldval != BBT_BLOCK_RESERVED) |
1047 | if (oldval != newval) | ||
1048 | update = 1; | 1040 | update = 1; |
1049 | block += 2; | 1041 | block++; |
1050 | } | 1042 | } |
1051 | /* | 1043 | /* |
1052 | * If we want reserved blocks to be recorded to flash, and some | 1044 | * If we want reserved blocks to be recorded to flash, and some |
@@ -1054,7 +1046,8 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) | |||
1054 | * bbts. This should only happen once. | 1046 | * bbts. This should only happen once. |
1055 | */ | 1047 | */ |
1056 | if (update && td->reserved_block_code) | 1048 | if (update && td->reserved_block_code) |
1057 | nand_update_bbt(mtd, (loff_t)(block - 2) << (this->bbt_erase_shift - 1)); | 1049 | nand_update_bbt(mtd, (loff_t)(block - 1) << |
1050 | this->bbt_erase_shift); | ||
1058 | } | 1051 | } |
1059 | } | 1052 | } |
1060 | 1053 | ||
@@ -1180,13 +1173,13 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) | |||
1180 | } | 1173 | } |
1181 | 1174 | ||
1182 | /** | 1175 | /** |
1183 | * nand_update_bbt - [NAND Interface] update bad block table(s) | 1176 | * nand_update_bbt - update bad block table(s) |
1184 | * @mtd: MTD device structure | 1177 | * @mtd: MTD device structure |
1185 | * @offs: the offset of the newly marked block | 1178 | * @offs: the offset of the newly marked block |
1186 | * | 1179 | * |
1187 | * The function updates the bad block table(s). | 1180 | * The function updates the bad block table(s). |
1188 | */ | 1181 | */ |
1189 | int nand_update_bbt(struct mtd_info *mtd, loff_t offs) | 1182 | static int nand_update_bbt(struct mtd_info *mtd, loff_t offs) |
1190 | { | 1183 | { |
1191 | struct nand_chip *this = mtd->priv; | 1184 | struct nand_chip *this = mtd->priv; |
1192 | int len, res = 0; | 1185 | int len, res = 0; |
@@ -1356,28 +1349,47 @@ int nand_default_bbt(struct mtd_info *mtd) | |||
1356 | int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) | 1349 | int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) |
1357 | { | 1350 | { |
1358 | struct nand_chip *this = mtd->priv; | 1351 | struct nand_chip *this = mtd->priv; |
1359 | int block; | 1352 | int block, res; |
1360 | uint8_t res; | ||
1361 | 1353 | ||
1362 | /* Get block number * 2 */ | 1354 | block = (int)(offs >> this->bbt_erase_shift); |
1363 | block = (int)(offs >> (this->bbt_erase_shift - 1)); | 1355 | res = bbt_get_entry(this, block); |
1364 | res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03; | ||
1365 | 1356 | ||
1366 | pr_debug("nand_isbad_bbt(): bbt info for offs 0x%08x: " | 1357 | pr_debug("nand_isbad_bbt(): bbt info for offs 0x%08x: " |
1367 | "(block %d) 0x%02x\n", | 1358 | "(block %d) 0x%02x\n", |
1368 | (unsigned int)offs, block >> 1, res); | 1359 | (unsigned int)offs, block, res); |
1369 | 1360 | ||
1370 | switch ((int)res) { | 1361 | switch (res) { |
1371 | case 0x00: | 1362 | case BBT_BLOCK_GOOD: |
1372 | return 0; | 1363 | return 0; |
1373 | case 0x01: | 1364 | case BBT_BLOCK_WORN: |
1374 | return 1; | 1365 | return 1; |
1375 | case 0x02: | 1366 | case BBT_BLOCK_RESERVED: |
1376 | return allowbbt ? 0 : 1; | 1367 | return allowbbt ? 0 : 1; |
1377 | } | 1368 | } |
1378 | return 1; | 1369 | return 1; |
1379 | } | 1370 | } |
1380 | 1371 | ||
1372 | /** | ||
1373 | * nand_markbad_bbt - [NAND Interface] Mark a block bad in the BBT | ||
1374 | * @mtd: MTD device structure | ||
1375 | * @offs: offset of the bad block | ||
1376 | */ | ||
1377 | int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs) | ||
1378 | { | ||
1379 | struct nand_chip *this = mtd->priv; | ||
1380 | int block, ret = 0; | ||
1381 | |||
1382 | block = (int)(offs >> this->bbt_erase_shift); | ||
1383 | |||
1384 | /* Mark bad block in memory */ | ||
1385 | bbt_mark_entry(this, block, BBT_BLOCK_WORN); | ||
1386 | |||
1387 | /* Update flash-based bad block table */ | ||
1388 | if (this->bbt_options & NAND_BBT_USE_FLASH) | ||
1389 | ret = nand_update_bbt(mtd, offs); | ||
1390 | |||
1391 | return ret; | ||
1392 | } | ||
1393 | |||
1381 | EXPORT_SYMBOL(nand_scan_bbt); | 1394 | EXPORT_SYMBOL(nand_scan_bbt); |
1382 | EXPORT_SYMBOL(nand_default_bbt); | 1395 | EXPORT_SYMBOL(nand_default_bbt); |
1383 | EXPORT_SYMBOL_GPL(nand_update_bbt); | ||
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index 683813a46a90..a87b0a3afa35 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c | |||
@@ -33,16 +33,16 @@ struct nand_flash_dev nand_flash_ids[] = { | |||
33 | */ | 33 | */ |
34 | {"TC58NVG2S0F 4G 3.3V 8-bit", | 34 | {"TC58NVG2S0F 4G 3.3V 8-bit", |
35 | { .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08} }, | 35 | { .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08} }, |
36 | SZ_4K, SZ_512, SZ_256K, 0, 8, 224}, | 36 | SZ_4K, SZ_512, SZ_256K, 0, 8, 224, NAND_ECC_INFO(4, SZ_512) }, |
37 | {"TC58NVG3S0F 8G 3.3V 8-bit", | 37 | {"TC58NVG3S0F 8G 3.3V 8-bit", |
38 | { .id = {0x98, 0xd3, 0x90, 0x26, 0x76, 0x15, 0x02, 0x08} }, | 38 | { .id = {0x98, 0xd3, 0x90, 0x26, 0x76, 0x15, 0x02, 0x08} }, |
39 | SZ_4K, SZ_1K, SZ_256K, 0, 8, 232}, | 39 | SZ_4K, SZ_1K, SZ_256K, 0, 8, 232, NAND_ECC_INFO(4, SZ_512) }, |
40 | {"TC58NVG5D2 32G 3.3V 8-bit", | 40 | {"TC58NVG5D2 32G 3.3V 8-bit", |
41 | { .id = {0x98, 0xd7, 0x94, 0x32, 0x76, 0x56, 0x09, 0x00} }, | 41 | { .id = {0x98, 0xd7, 0x94, 0x32, 0x76, 0x56, 0x09, 0x00} }, |
42 | SZ_8K, SZ_4K, SZ_1M, 0, 8, 640}, | 42 | SZ_8K, SZ_4K, SZ_1M, 0, 8, 640, NAND_ECC_INFO(40, SZ_1K) }, |
43 | {"TC58NVG6D2 64G 3.3V 8-bit", | 43 | {"TC58NVG6D2 64G 3.3V 8-bit", |
44 | { .id = {0x98, 0xde, 0x94, 0x82, 0x76, 0x56, 0x04, 0x20} }, | 44 | { .id = {0x98, 0xde, 0x94, 0x82, 0x76, 0x56, 0x04, 0x20} }, |
45 | SZ_8K, SZ_8K, SZ_2M, 0, 8, 640}, | 45 | SZ_8K, SZ_8K, SZ_2M, 0, 8, 640, NAND_ECC_INFO(40, SZ_1K) }, |
46 | 46 | ||
47 | LEGACY_ID_NAND("NAND 4MiB 5V 8-bit", 0x6B, 4, SZ_8K, SP_OPTIONS), | 47 | LEGACY_ID_NAND("NAND 4MiB 5V 8-bit", 0x6B, 4, SZ_8K, SP_OPTIONS), |
48 | LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS), | 48 | LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS), |
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index cb38f3d94218..bdc1d15369f8 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
@@ -205,7 +205,7 @@ MODULE_PARM_DESC(bch, "Enable BCH ecc and set how many bits should " | |||
205 | 205 | ||
206 | /* Calculate the page offset in flash RAM image by (row, column) address */ | 206 | /* Calculate the page offset in flash RAM image by (row, column) address */ |
207 | #define NS_RAW_OFFSET(ns) \ | 207 | #define NS_RAW_OFFSET(ns) \ |
208 | (((ns)->regs.row << (ns)->geom.pgshift) + ((ns)->regs.row * (ns)->geom.oobsz) + (ns)->regs.column) | 208 | (((ns)->regs.row * (ns)->geom.pgszoob) + (ns)->regs.column) |
209 | 209 | ||
210 | /* Calculate the OOB offset in flash RAM image by (row, column) address */ | 210 | /* Calculate the OOB offset in flash RAM image by (row, column) address */ |
211 | #define NS_RAW_OFFSET_OOB(ns) (NS_RAW_OFFSET(ns) + ns->geom.pgsz) | 211 | #define NS_RAW_OFFSET_OOB(ns) (NS_RAW_OFFSET(ns) + ns->geom.pgsz) |
@@ -336,7 +336,6 @@ struct nandsim { | |||
336 | uint pgsec; /* number of pages per sector */ | 336 | uint pgsec; /* number of pages per sector */ |
337 | uint secshift; /* bits number in sector size */ | 337 | uint secshift; /* bits number in sector size */ |
338 | uint pgshift; /* bits number in page size */ | 338 | uint pgshift; /* bits number in page size */ |
339 | uint oobshift; /* bits number in OOB size */ | ||
340 | uint pgaddrbytes; /* bytes per page address */ | 339 | uint pgaddrbytes; /* bytes per page address */ |
341 | uint secaddrbytes; /* bytes per sector address */ | 340 | uint secaddrbytes; /* bytes per sector address */ |
342 | uint idbytes; /* the number ID bytes that this chip outputs */ | 341 | uint idbytes; /* the number ID bytes that this chip outputs */ |
@@ -363,7 +362,7 @@ struct nandsim { | |||
363 | 362 | ||
364 | /* Fields needed when using a cache file */ | 363 | /* Fields needed when using a cache file */ |
365 | struct file *cfile; /* Open file */ | 364 | struct file *cfile; /* Open file */ |
366 | unsigned char *pages_written; /* Which pages have been written */ | 365 | unsigned long *pages_written; /* Which pages have been written */ |
367 | void *file_buf; | 366 | void *file_buf; |
368 | struct page *held_pages[NS_MAX_HELD_PAGES]; | 367 | struct page *held_pages[NS_MAX_HELD_PAGES]; |
369 | int held_cnt; | 368 | int held_cnt; |
@@ -586,7 +585,8 @@ static int alloc_device(struct nandsim *ns) | |||
586 | err = -EINVAL; | 585 | err = -EINVAL; |
587 | goto err_close; | 586 | goto err_close; |
588 | } | 587 | } |
589 | ns->pages_written = vzalloc(ns->geom.pgnum); | 588 | ns->pages_written = vzalloc(BITS_TO_LONGS(ns->geom.pgnum) * |
589 | sizeof(unsigned long)); | ||
590 | if (!ns->pages_written) { | 590 | if (!ns->pages_written) { |
591 | NS_ERR("alloc_device: unable to allocate pages written array\n"); | 591 | NS_ERR("alloc_device: unable to allocate pages written array\n"); |
592 | err = -ENOMEM; | 592 | err = -ENOMEM; |
@@ -653,9 +653,7 @@ static void free_device(struct nandsim *ns) | |||
653 | 653 | ||
654 | static char *get_partition_name(int i) | 654 | static char *get_partition_name(int i) |
655 | { | 655 | { |
656 | char buf[64]; | 656 | return kasprintf(GFP_KERNEL, "NAND simulator partition %d", i); |
657 | sprintf(buf, "NAND simulator partition %d", i); | ||
658 | return kstrdup(buf, GFP_KERNEL); | ||
659 | } | 657 | } |
660 | 658 | ||
661 | /* | 659 | /* |
@@ -690,7 +688,6 @@ static int init_nandsim(struct mtd_info *mtd) | |||
690 | ns->geom.totszoob = ns->geom.totsz + (uint64_t)ns->geom.pgnum * ns->geom.oobsz; | 688 | ns->geom.totszoob = ns->geom.totsz + (uint64_t)ns->geom.pgnum * ns->geom.oobsz; |
691 | ns->geom.secshift = ffs(ns->geom.secsz) - 1; | 689 | ns->geom.secshift = ffs(ns->geom.secsz) - 1; |
692 | ns->geom.pgshift = chip->page_shift; | 690 | ns->geom.pgshift = chip->page_shift; |
693 | ns->geom.oobshift = ffs(ns->geom.oobsz) - 1; | ||
694 | ns->geom.pgsec = ns->geom.secsz / ns->geom.pgsz; | 691 | ns->geom.pgsec = ns->geom.secsz / ns->geom.pgsz; |
695 | ns->geom.secszoob = ns->geom.secsz + ns->geom.oobsz * ns->geom.pgsec; | 692 | ns->geom.secszoob = ns->geom.secsz + ns->geom.oobsz * ns->geom.pgsec; |
696 | ns->options = 0; | 693 | ns->options = 0; |
@@ -761,12 +758,6 @@ static int init_nandsim(struct mtd_info *mtd) | |||
761 | ns->nbparts += 1; | 758 | ns->nbparts += 1; |
762 | } | 759 | } |
763 | 760 | ||
764 | /* Detect how many ID bytes the NAND chip outputs */ | ||
765 | for (i = 0; nand_flash_ids[i].name != NULL; i++) { | ||
766 | if (second_id_byte != nand_flash_ids[i].dev_id) | ||
767 | continue; | ||
768 | } | ||
769 | |||
770 | if (ns->busw == 16) | 761 | if (ns->busw == 16) |
771 | NS_WARN("16-bit flashes support wasn't tested\n"); | 762 | NS_WARN("16-bit flashes support wasn't tested\n"); |
772 | 763 | ||
@@ -780,7 +771,7 @@ static int init_nandsim(struct mtd_info *mtd) | |||
780 | printk("bus width: %u\n", ns->busw); | 771 | printk("bus width: %u\n", ns->busw); |
781 | printk("bits in sector size: %u\n", ns->geom.secshift); | 772 | printk("bits in sector size: %u\n", ns->geom.secshift); |
782 | printk("bits in page size: %u\n", ns->geom.pgshift); | 773 | printk("bits in page size: %u\n", ns->geom.pgshift); |
783 | printk("bits in OOB size: %u\n", ns->geom.oobshift); | 774 | printk("bits in OOB size: %u\n", ffs(ns->geom.oobsz) - 1); |
784 | printk("flash size with OOB: %llu KiB\n", | 775 | printk("flash size with OOB: %llu KiB\n", |
785 | (unsigned long long)ns->geom.totszoob >> 10); | 776 | (unsigned long long)ns->geom.totszoob >> 10); |
786 | printk("page address bytes: %u\n", ns->geom.pgaddrbytes); | 777 | printk("page address bytes: %u\n", ns->geom.pgaddrbytes); |
@@ -1442,7 +1433,7 @@ static inline u_char *NS_PAGE_BYTE_OFF(struct nandsim *ns) | |||
1442 | return NS_GET_PAGE(ns)->byte + ns->regs.column + ns->regs.off; | 1433 | return NS_GET_PAGE(ns)->byte + ns->regs.column + ns->regs.off; |
1443 | } | 1434 | } |
1444 | 1435 | ||
1445 | int do_read_error(struct nandsim *ns, int num) | 1436 | static int do_read_error(struct nandsim *ns, int num) |
1446 | { | 1437 | { |
1447 | unsigned int page_no = ns->regs.row; | 1438 | unsigned int page_no = ns->regs.row; |
1448 | 1439 | ||
@@ -1454,7 +1445,7 @@ int do_read_error(struct nandsim *ns, int num) | |||
1454 | return 0; | 1445 | return 0; |
1455 | } | 1446 | } |
1456 | 1447 | ||
1457 | void do_bit_flips(struct nandsim *ns, int num) | 1448 | static void do_bit_flips(struct nandsim *ns, int num) |
1458 | { | 1449 | { |
1459 | if (bitflips && prandom_u32() < (1 << 22)) { | 1450 | if (bitflips && prandom_u32() < (1 << 22)) { |
1460 | int flips = 1; | 1451 | int flips = 1; |
@@ -1479,7 +1470,7 @@ static void read_page(struct nandsim *ns, int num) | |||
1479 | union ns_mem *mypage; | 1470 | union ns_mem *mypage; |
1480 | 1471 | ||
1481 | if (ns->cfile) { | 1472 | if (ns->cfile) { |
1482 | if (!ns->pages_written[ns->regs.row]) { | 1473 | if (!test_bit(ns->regs.row, ns->pages_written)) { |
1483 | NS_DBG("read_page: page %d not written\n", ns->regs.row); | 1474 | NS_DBG("read_page: page %d not written\n", ns->regs.row); |
1484 | memset(ns->buf.byte, 0xFF, num); | 1475 | memset(ns->buf.byte, 0xFF, num); |
1485 | } else { | 1476 | } else { |
@@ -1490,7 +1481,7 @@ static void read_page(struct nandsim *ns, int num) | |||
1490 | ns->regs.row, ns->regs.column + ns->regs.off); | 1481 | ns->regs.row, ns->regs.column + ns->regs.off); |
1491 | if (do_read_error(ns, num)) | 1482 | if (do_read_error(ns, num)) |
1492 | return; | 1483 | return; |
1493 | pos = (loff_t)ns->regs.row * ns->geom.pgszoob + ns->regs.column + ns->regs.off; | 1484 | pos = (loff_t)NS_RAW_OFFSET(ns) + ns->regs.off; |
1494 | tx = read_file(ns, ns->cfile, ns->buf.byte, num, pos); | 1485 | tx = read_file(ns, ns->cfile, ns->buf.byte, num, pos); |
1495 | if (tx != num) { | 1486 | if (tx != num) { |
1496 | NS_ERR("read_page: read error for page %d ret %ld\n", ns->regs.row, (long)tx); | 1487 | NS_ERR("read_page: read error for page %d ret %ld\n", ns->regs.row, (long)tx); |
@@ -1525,9 +1516,9 @@ static void erase_sector(struct nandsim *ns) | |||
1525 | 1516 | ||
1526 | if (ns->cfile) { | 1517 | if (ns->cfile) { |
1527 | for (i = 0; i < ns->geom.pgsec; i++) | 1518 | for (i = 0; i < ns->geom.pgsec; i++) |
1528 | if (ns->pages_written[ns->regs.row + i]) { | 1519 | if (__test_and_clear_bit(ns->regs.row + i, |
1520 | ns->pages_written)) { | ||
1529 | NS_DBG("erase_sector: freeing page %d\n", ns->regs.row + i); | 1521 | NS_DBG("erase_sector: freeing page %d\n", ns->regs.row + i); |
1530 | ns->pages_written[ns->regs.row + i] = 0; | ||
1531 | } | 1522 | } |
1532 | return; | 1523 | return; |
1533 | } | 1524 | } |
@@ -1559,8 +1550,8 @@ static int prog_page(struct nandsim *ns, int num) | |||
1559 | 1550 | ||
1560 | NS_DBG("prog_page: writing page %d\n", ns->regs.row); | 1551 | NS_DBG("prog_page: writing page %d\n", ns->regs.row); |
1561 | pg_off = ns->file_buf + ns->regs.column + ns->regs.off; | 1552 | pg_off = ns->file_buf + ns->regs.column + ns->regs.off; |
1562 | off = (loff_t)ns->regs.row * ns->geom.pgszoob + ns->regs.column + ns->regs.off; | 1553 | off = (loff_t)NS_RAW_OFFSET(ns) + ns->regs.off; |
1563 | if (!ns->pages_written[ns->regs.row]) { | 1554 | if (!test_bit(ns->regs.row, ns->pages_written)) { |
1564 | all = 1; | 1555 | all = 1; |
1565 | memset(ns->file_buf, 0xff, ns->geom.pgszoob); | 1556 | memset(ns->file_buf, 0xff, ns->geom.pgszoob); |
1566 | } else { | 1557 | } else { |
@@ -1580,7 +1571,7 @@ static int prog_page(struct nandsim *ns, int num) | |||
1580 | NS_ERR("prog_page: write error for page %d ret %ld\n", ns->regs.row, (long)tx); | 1571 | NS_ERR("prog_page: write error for page %d ret %ld\n", ns->regs.row, (long)tx); |
1581 | return -1; | 1572 | return -1; |
1582 | } | 1573 | } |
1583 | ns->pages_written[ns->regs.row] = 1; | 1574 | __set_bit(ns->regs.row, ns->pages_written); |
1584 | } else { | 1575 | } else { |
1585 | tx = write_file(ns, ns->cfile, pg_off, num, off); | 1576 | tx = write_file(ns, ns->cfile, pg_off, num, off); |
1586 | if (tx != num) { | 1577 | if (tx != num) { |
diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c index cd6be2ed53a8..52115151e4a7 100644 --- a/drivers/mtd/nand/nuc900_nand.c +++ b/drivers/mtd/nand/nuc900_nand.c | |||
@@ -324,8 +324,6 @@ static int nuc900_nand_remove(struct platform_device *pdev) | |||
324 | 324 | ||
325 | kfree(nuc900_nand); | 325 | kfree(nuc900_nand); |
326 | 326 | ||
327 | platform_set_drvdata(pdev, NULL); | ||
328 | |||
329 | return 0; | 327 | return 0; |
330 | } | 328 | } |
331 | 329 | ||
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 81b80af55872..4ecf0e5fd484 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
@@ -154,7 +154,7 @@ static struct nand_ecclayout omap_oobinfo; | |||
154 | */ | 154 | */ |
155 | static uint8_t scan_ff_pattern[] = { 0xff }; | 155 | static uint8_t scan_ff_pattern[] = { 0xff }; |
156 | static struct nand_bbt_descr bb_descrip_flashbased = { | 156 | static struct nand_bbt_descr bb_descrip_flashbased = { |
157 | .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES, | 157 | .options = NAND_BBT_SCANALLPAGES, |
158 | .offs = 0, | 158 | .offs = 0, |
159 | .len = 1, | 159 | .len = 1, |
160 | .pattern = scan_ff_pattern, | 160 | .pattern = scan_ff_pattern, |
@@ -1831,7 +1831,7 @@ static int omap_nand_probe(struct platform_device *pdev) | |||
1831 | struct resource *res; | 1831 | struct resource *res; |
1832 | struct mtd_part_parser_data ppdata = {}; | 1832 | struct mtd_part_parser_data ppdata = {}; |
1833 | 1833 | ||
1834 | pdata = pdev->dev.platform_data; | 1834 | pdata = dev_get_platdata(&pdev->dev); |
1835 | if (pdata == NULL) { | 1835 | if (pdata == NULL) { |
1836 | dev_err(&pdev->dev, "platform data missing\n"); | 1836 | dev_err(&pdev->dev, "platform data missing\n"); |
1837 | return -ENODEV; | 1837 | return -ENODEV; |
@@ -2087,7 +2087,6 @@ static int omap_nand_remove(struct platform_device *pdev) | |||
2087 | mtd); | 2087 | mtd); |
2088 | omap3_free_bch(&info->mtd); | 2088 | omap3_free_bch(&info->mtd); |
2089 | 2089 | ||
2090 | platform_set_drvdata(pdev, NULL); | ||
2091 | if (info->dma) | 2090 | if (info->dma) |
2092 | dma_release_channel(info->dma); | 2091 | dma_release_channel(info->dma); |
2093 | 2092 | ||
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index 8fbd00208610..a393a5b6ce1e 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c | |||
@@ -130,8 +130,9 @@ static int __init orion_nand_probe(struct platform_device *pdev) | |||
130 | if (!of_property_read_u32(pdev->dev.of_node, | 130 | if (!of_property_read_u32(pdev->dev.of_node, |
131 | "chip-delay", &val)) | 131 | "chip-delay", &val)) |
132 | board->chip_delay = (u8)val; | 132 | board->chip_delay = (u8)val; |
133 | } else | 133 | } else { |
134 | board = pdev->dev.platform_data; | 134 | board = dev_get_platdata(&pdev->dev); |
135 | } | ||
135 | 136 | ||
136 | mtd->priv = nc; | 137 | mtd->priv = nc; |
137 | mtd->owner = THIS_MODULE; | 138 | mtd->owner = THIS_MODULE; |
@@ -186,7 +187,6 @@ no_dev: | |||
186 | clk_disable_unprepare(clk); | 187 | clk_disable_unprepare(clk); |
187 | clk_put(clk); | 188 | clk_put(clk); |
188 | } | 189 | } |
189 | platform_set_drvdata(pdev, NULL); | ||
190 | iounmap(io_base); | 190 | iounmap(io_base); |
191 | no_res: | 191 | no_res: |
192 | kfree(nc); | 192 | kfree(nc); |
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index c004566a9ad2..cad4cdc9df39 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c | |||
@@ -30,7 +30,7 @@ static const char *part_probe_types[] = { "cmdlinepart", NULL }; | |||
30 | */ | 30 | */ |
31 | static int plat_nand_probe(struct platform_device *pdev) | 31 | static int plat_nand_probe(struct platform_device *pdev) |
32 | { | 32 | { |
33 | struct platform_nand_data *pdata = pdev->dev.platform_data; | 33 | struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev); |
34 | struct mtd_part_parser_data ppdata; | 34 | struct mtd_part_parser_data ppdata; |
35 | struct plat_nand_data *data; | 35 | struct plat_nand_data *data; |
36 | struct resource *res; | 36 | struct resource *res; |
@@ -122,7 +122,6 @@ static int plat_nand_probe(struct platform_device *pdev) | |||
122 | out: | 122 | out: |
123 | if (pdata->ctrl.remove) | 123 | if (pdata->ctrl.remove) |
124 | pdata->ctrl.remove(pdev); | 124 | pdata->ctrl.remove(pdev); |
125 | platform_set_drvdata(pdev, NULL); | ||
126 | iounmap(data->io_base); | 125 | iounmap(data->io_base); |
127 | out_release_io: | 126 | out_release_io: |
128 | release_mem_region(res->start, resource_size(res)); | 127 | release_mem_region(res->start, resource_size(res)); |
@@ -137,7 +136,7 @@ out_free: | |||
137 | static int plat_nand_remove(struct platform_device *pdev) | 136 | static int plat_nand_remove(struct platform_device *pdev) |
138 | { | 137 | { |
139 | struct plat_nand_data *data = platform_get_drvdata(pdev); | 138 | struct plat_nand_data *data = platform_get_drvdata(pdev); |
140 | struct platform_nand_data *pdata = pdev->dev.platform_data; | 139 | struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev); |
141 | struct resource *res; | 140 | struct resource *res; |
142 | 141 | ||
143 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 142 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index dec80ca6a5ce..5db900d917f9 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
@@ -25,7 +25,14 @@ | |||
25 | #include <linux/of.h> | 25 | #include <linux/of.h> |
26 | #include <linux/of_device.h> | 26 | #include <linux/of_device.h> |
27 | 27 | ||
28 | #if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP) | ||
29 | #define ARCH_HAS_DMA | ||
30 | #endif | ||
31 | |||
32 | #ifdef ARCH_HAS_DMA | ||
28 | #include <mach/dma.h> | 33 | #include <mach/dma.h> |
34 | #endif | ||
35 | |||
29 | #include <linux/platform_data/mtd-nand-pxa3xx.h> | 36 | #include <linux/platform_data/mtd-nand-pxa3xx.h> |
30 | 37 | ||
31 | #define CHIP_DELAY_TIMEOUT (2 * HZ/10) | 38 | #define CHIP_DELAY_TIMEOUT (2 * HZ/10) |
@@ -80,6 +87,7 @@ | |||
80 | #define NDSR_RDDREQ (0x1 << 1) | 87 | #define NDSR_RDDREQ (0x1 << 1) |
81 | #define NDSR_WRCMDREQ (0x1) | 88 | #define NDSR_WRCMDREQ (0x1) |
82 | 89 | ||
90 | #define NDCB0_LEN_OVRD (0x1 << 28) | ||
83 | #define NDCB0_ST_ROW_EN (0x1 << 26) | 91 | #define NDCB0_ST_ROW_EN (0x1 << 26) |
84 | #define NDCB0_AUTO_RS (0x1 << 25) | 92 | #define NDCB0_AUTO_RS (0x1 << 25) |
85 | #define NDCB0_CSEL (0x1 << 24) | 93 | #define NDCB0_CSEL (0x1 << 24) |
@@ -123,9 +131,13 @@ enum { | |||
123 | STATE_READY, | 131 | STATE_READY, |
124 | }; | 132 | }; |
125 | 133 | ||
134 | enum pxa3xx_nand_variant { | ||
135 | PXA3XX_NAND_VARIANT_PXA, | ||
136 | PXA3XX_NAND_VARIANT_ARMADA370, | ||
137 | }; | ||
138 | |||
126 | struct pxa3xx_nand_host { | 139 | struct pxa3xx_nand_host { |
127 | struct nand_chip chip; | 140 | struct nand_chip chip; |
128 | struct pxa3xx_nand_cmdset *cmdset; | ||
129 | struct mtd_info *mtd; | 141 | struct mtd_info *mtd; |
130 | void *info_data; | 142 | void *info_data; |
131 | 143 | ||
@@ -139,10 +151,6 @@ struct pxa3xx_nand_host { | |||
139 | unsigned int row_addr_cycles; | 151 | unsigned int row_addr_cycles; |
140 | size_t read_id_bytes; | 152 | size_t read_id_bytes; |
141 | 153 | ||
142 | /* cached register value */ | ||
143 | uint32_t reg_ndcr; | ||
144 | uint32_t ndtr0cs0; | ||
145 | uint32_t ndtr1cs0; | ||
146 | }; | 154 | }; |
147 | 155 | ||
148 | struct pxa3xx_nand_info { | 156 | struct pxa3xx_nand_info { |
@@ -171,9 +179,16 @@ struct pxa3xx_nand_info { | |||
171 | struct pxa3xx_nand_host *host[NUM_CHIP_SELECT]; | 179 | struct pxa3xx_nand_host *host[NUM_CHIP_SELECT]; |
172 | unsigned int state; | 180 | unsigned int state; |
173 | 181 | ||
182 | /* | ||
183 | * This driver supports NFCv1 (as found in PXA SoC) | ||
184 | * and NFCv2 (as found in Armada 370/XP SoC). | ||
185 | */ | ||
186 | enum pxa3xx_nand_variant variant; | ||
187 | |||
174 | int cs; | 188 | int cs; |
175 | int use_ecc; /* use HW ECC ? */ | 189 | int use_ecc; /* use HW ECC ? */ |
176 | int use_dma; /* use DMA ? */ | 190 | int use_dma; /* use DMA ? */ |
191 | int use_spare; /* use spare ? */ | ||
177 | int is_ready; | 192 | int is_ready; |
178 | 193 | ||
179 | unsigned int page_size; /* page size of attached chip */ | 194 | unsigned int page_size; /* page size of attached chip */ |
@@ -181,33 +196,22 @@ struct pxa3xx_nand_info { | |||
181 | unsigned int oob_size; | 196 | unsigned int oob_size; |
182 | int retcode; | 197 | int retcode; |
183 | 198 | ||
199 | /* cached register value */ | ||
200 | uint32_t reg_ndcr; | ||
201 | uint32_t ndtr0cs0; | ||
202 | uint32_t ndtr1cs0; | ||
203 | |||
184 | /* generated NDCBx register values */ | 204 | /* generated NDCBx register values */ |
185 | uint32_t ndcb0; | 205 | uint32_t ndcb0; |
186 | uint32_t ndcb1; | 206 | uint32_t ndcb1; |
187 | uint32_t ndcb2; | 207 | uint32_t ndcb2; |
208 | uint32_t ndcb3; | ||
188 | }; | 209 | }; |
189 | 210 | ||
190 | static bool use_dma = 1; | 211 | static bool use_dma = 1; |
191 | module_param(use_dma, bool, 0444); | 212 | module_param(use_dma, bool, 0444); |
192 | MODULE_PARM_DESC(use_dma, "enable DMA for data transferring to/from NAND HW"); | 213 | MODULE_PARM_DESC(use_dma, "enable DMA for data transferring to/from NAND HW"); |
193 | 214 | ||
194 | /* | ||
195 | * Default NAND flash controller configuration setup by the | ||
196 | * bootloader. This configuration is used only when pdata->keep_config is set | ||
197 | */ | ||
198 | static struct pxa3xx_nand_cmdset default_cmdset = { | ||
199 | .read1 = 0x3000, | ||
200 | .read2 = 0x0050, | ||
201 | .program = 0x1080, | ||
202 | .read_status = 0x0070, | ||
203 | .read_id = 0x0090, | ||
204 | .erase = 0xD060, | ||
205 | .reset = 0x00FF, | ||
206 | .lock = 0x002A, | ||
207 | .unlock = 0x2423, | ||
208 | .lock_status = 0x007A, | ||
209 | }; | ||
210 | |||
211 | static struct pxa3xx_nand_timing timing[] = { | 215 | static struct pxa3xx_nand_timing timing[] = { |
212 | { 40, 80, 60, 100, 80, 100, 90000, 400, 40, }, | 216 | { 40, 80, 60, 100, 80, 100, 90000, 400, 40, }, |
213 | { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, | 217 | { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, |
@@ -230,8 +234,6 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = { | |||
230 | /* Define a default flash type setting serve as flash detecting only */ | 234 | /* Define a default flash type setting serve as flash detecting only */ |
231 | #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0]) | 235 | #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0]) |
232 | 236 | ||
233 | const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL}; | ||
234 | |||
235 | #define NDTR0_tCH(c) (min((c), 7) << 19) | 237 | #define NDTR0_tCH(c) (min((c), 7) << 19) |
236 | #define NDTR0_tCS(c) (min((c), 7) << 16) | 238 | #define NDTR0_tCS(c) (min((c), 7) << 16) |
237 | #define NDTR0_tWH(c) (min((c), 7) << 11) | 239 | #define NDTR0_tWH(c) (min((c), 7) << 11) |
@@ -264,8 +266,8 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host, | |||
264 | NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) | | 266 | NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) | |
265 | NDTR1_tAR(ns2cycle(t->tAR, nand_clk)); | 267 | NDTR1_tAR(ns2cycle(t->tAR, nand_clk)); |
266 | 268 | ||
267 | host->ndtr0cs0 = ndtr0; | 269 | info->ndtr0cs0 = ndtr0; |
268 | host->ndtr1cs0 = ndtr1; | 270 | info->ndtr1cs0 = ndtr1; |
269 | nand_writel(info, NDTR0CS0, ndtr0); | 271 | nand_writel(info, NDTR0CS0, ndtr0); |
270 | nand_writel(info, NDTR1CS0, ndtr1); | 272 | nand_writel(info, NDTR1CS0, ndtr1); |
271 | } | 273 | } |
@@ -273,7 +275,7 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host, | |||
273 | static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) | 275 | static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) |
274 | { | 276 | { |
275 | struct pxa3xx_nand_host *host = info->host[info->cs]; | 277 | struct pxa3xx_nand_host *host = info->host[info->cs]; |
276 | int oob_enable = host->reg_ndcr & NDCR_SPARE_EN; | 278 | int oob_enable = info->reg_ndcr & NDCR_SPARE_EN; |
277 | 279 | ||
278 | info->data_size = host->page_size; | 280 | info->data_size = host->page_size; |
279 | if (!oob_enable) { | 281 | if (!oob_enable) { |
@@ -299,12 +301,25 @@ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) | |||
299 | */ | 301 | */ |
300 | static void pxa3xx_nand_start(struct pxa3xx_nand_info *info) | 302 | static void pxa3xx_nand_start(struct pxa3xx_nand_info *info) |
301 | { | 303 | { |
302 | struct pxa3xx_nand_host *host = info->host[info->cs]; | ||
303 | uint32_t ndcr; | 304 | uint32_t ndcr; |
304 | 305 | ||
305 | ndcr = host->reg_ndcr; | 306 | ndcr = info->reg_ndcr; |
306 | ndcr |= info->use_ecc ? NDCR_ECC_EN : 0; | 307 | |
307 | ndcr |= info->use_dma ? NDCR_DMA_EN : 0; | 308 | if (info->use_ecc) |
309 | ndcr |= NDCR_ECC_EN; | ||
310 | else | ||
311 | ndcr &= ~NDCR_ECC_EN; | ||
312 | |||
313 | if (info->use_dma) | ||
314 | ndcr |= NDCR_DMA_EN; | ||
315 | else | ||
316 | ndcr &= ~NDCR_DMA_EN; | ||
317 | |||
318 | if (info->use_spare) | ||
319 | ndcr |= NDCR_SPARE_EN; | ||
320 | else | ||
321 | ndcr &= ~NDCR_SPARE_EN; | ||
322 | |||
308 | ndcr |= NDCR_ND_RUN; | 323 | ndcr |= NDCR_ND_RUN; |
309 | 324 | ||
310 | /* clear status bits and run */ | 325 | /* clear status bits and run */ |
@@ -333,7 +348,8 @@ static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info) | |||
333 | nand_writel(info, NDSR, NDSR_MASK); | 348 | nand_writel(info, NDSR, NDSR_MASK); |
334 | } | 349 | } |
335 | 350 | ||
336 | static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) | 351 | static void __maybe_unused |
352 | enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) | ||
337 | { | 353 | { |
338 | uint32_t ndcr; | 354 | uint32_t ndcr; |
339 | 355 | ||
@@ -373,6 +389,7 @@ static void handle_data_pio(struct pxa3xx_nand_info *info) | |||
373 | } | 389 | } |
374 | } | 390 | } |
375 | 391 | ||
392 | #ifdef ARCH_HAS_DMA | ||
376 | static void start_data_dma(struct pxa3xx_nand_info *info) | 393 | static void start_data_dma(struct pxa3xx_nand_info *info) |
377 | { | 394 | { |
378 | struct pxa_dma_desc *desc = info->data_desc; | 395 | struct pxa_dma_desc *desc = info->data_desc; |
@@ -419,6 +436,10 @@ static void pxa3xx_nand_data_dma_irq(int channel, void *data) | |||
419 | enable_int(info, NDCR_INT_MASK); | 436 | enable_int(info, NDCR_INT_MASK); |
420 | nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ); | 437 | nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ); |
421 | } | 438 | } |
439 | #else | ||
440 | static void start_data_dma(struct pxa3xx_nand_info *info) | ||
441 | {} | ||
442 | #endif | ||
422 | 443 | ||
423 | static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) | 444 | static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) |
424 | { | 445 | { |
@@ -467,9 +488,22 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) | |||
467 | nand_writel(info, NDSR, NDSR_WRCMDREQ); | 488 | nand_writel(info, NDSR, NDSR_WRCMDREQ); |
468 | status &= ~NDSR_WRCMDREQ; | 489 | status &= ~NDSR_WRCMDREQ; |
469 | info->state = STATE_CMD_HANDLE; | 490 | info->state = STATE_CMD_HANDLE; |
491 | |||
492 | /* | ||
493 | * Command buffer registers NDCB{0-2} (and optionally NDCB3) | ||
494 | * must be loaded by writing directly either 12 or 16 | ||
495 | * bytes directly to NDCB0, four bytes at a time. | ||
496 | * | ||
497 | * Direct write access to NDCB1, NDCB2 and NDCB3 is ignored | ||
498 | * but each NDCBx register can be read. | ||
499 | */ | ||
470 | nand_writel(info, NDCB0, info->ndcb0); | 500 | nand_writel(info, NDCB0, info->ndcb0); |
471 | nand_writel(info, NDCB0, info->ndcb1); | 501 | nand_writel(info, NDCB0, info->ndcb1); |
472 | nand_writel(info, NDCB0, info->ndcb2); | 502 | nand_writel(info, NDCB0, info->ndcb2); |
503 | |||
504 | /* NDCB3 register is available in NFCv2 (Armada 370/XP SoC) */ | ||
505 | if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) | ||
506 | nand_writel(info, NDCB0, info->ndcb3); | ||
473 | } | 507 | } |
474 | 508 | ||
475 | /* clear NDSR to let the controller exit the IRQ */ | 509 | /* clear NDSR to let the controller exit the IRQ */ |
@@ -491,7 +525,6 @@ static inline int is_buf_blank(uint8_t *buf, size_t len) | |||
491 | static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | 525 | static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, |
492 | uint16_t column, int page_addr) | 526 | uint16_t column, int page_addr) |
493 | { | 527 | { |
494 | uint16_t cmd; | ||
495 | int addr_cycle, exec_cmd; | 528 | int addr_cycle, exec_cmd; |
496 | struct pxa3xx_nand_host *host; | 529 | struct pxa3xx_nand_host *host; |
497 | struct mtd_info *mtd; | 530 | struct mtd_info *mtd; |
@@ -506,6 +539,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
506 | info->buf_count = 0; | 539 | info->buf_count = 0; |
507 | info->oob_size = 0; | 540 | info->oob_size = 0; |
508 | info->use_ecc = 0; | 541 | info->use_ecc = 0; |
542 | info->use_spare = 1; | ||
543 | info->use_dma = (use_dma) ? 1 : 0; | ||
509 | info->is_ready = 0; | 544 | info->is_ready = 0; |
510 | info->retcode = ERR_NONE; | 545 | info->retcode = ERR_NONE; |
511 | if (info->cs != 0) | 546 | if (info->cs != 0) |
@@ -520,12 +555,16 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
520 | case NAND_CMD_READOOB: | 555 | case NAND_CMD_READOOB: |
521 | pxa3xx_set_datasize(info); | 556 | pxa3xx_set_datasize(info); |
522 | break; | 557 | break; |
558 | case NAND_CMD_PARAM: | ||
559 | info->use_spare = 0; | ||
560 | break; | ||
523 | case NAND_CMD_SEQIN: | 561 | case NAND_CMD_SEQIN: |
524 | exec_cmd = 0; | 562 | exec_cmd = 0; |
525 | break; | 563 | break; |
526 | default: | 564 | default: |
527 | info->ndcb1 = 0; | 565 | info->ndcb1 = 0; |
528 | info->ndcb2 = 0; | 566 | info->ndcb2 = 0; |
567 | info->ndcb3 = 0; | ||
529 | break; | 568 | break; |
530 | } | 569 | } |
531 | 570 | ||
@@ -535,21 +574,17 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
535 | switch (command) { | 574 | switch (command) { |
536 | case NAND_CMD_READOOB: | 575 | case NAND_CMD_READOOB: |
537 | case NAND_CMD_READ0: | 576 | case NAND_CMD_READ0: |
538 | cmd = host->cmdset->read1; | 577 | info->buf_start = column; |
578 | info->ndcb0 |= NDCB0_CMD_TYPE(0) | ||
579 | | addr_cycle | ||
580 | | NAND_CMD_READ0; | ||
581 | |||
539 | if (command == NAND_CMD_READOOB) | 582 | if (command == NAND_CMD_READOOB) |
540 | info->buf_start = mtd->writesize + column; | 583 | info->buf_start += mtd->writesize; |
541 | else | ||
542 | info->buf_start = column; | ||
543 | 584 | ||
544 | if (unlikely(host->page_size < PAGE_CHUNK_SIZE)) | 585 | /* Second command setting for large pages */ |
545 | info->ndcb0 |= NDCB0_CMD_TYPE(0) | 586 | if (host->page_size >= PAGE_CHUNK_SIZE) |
546 | | addr_cycle | 587 | info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8); |
547 | | (cmd & NDCB0_CMD1_MASK); | ||
548 | else | ||
549 | info->ndcb0 |= NDCB0_CMD_TYPE(0) | ||
550 | | NDCB0_DBC | ||
551 | | addr_cycle | ||
552 | | cmd; | ||
553 | 588 | ||
554 | case NAND_CMD_SEQIN: | 589 | case NAND_CMD_SEQIN: |
555 | /* small page addr setting */ | 590 | /* small page addr setting */ |
@@ -580,49 +615,58 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
580 | break; | 615 | break; |
581 | } | 616 | } |
582 | 617 | ||
583 | cmd = host->cmdset->program; | ||
584 | info->ndcb0 |= NDCB0_CMD_TYPE(0x1) | 618 | info->ndcb0 |= NDCB0_CMD_TYPE(0x1) |
585 | | NDCB0_AUTO_RS | 619 | | NDCB0_AUTO_RS |
586 | | NDCB0_ST_ROW_EN | 620 | | NDCB0_ST_ROW_EN |
587 | | NDCB0_DBC | 621 | | NDCB0_DBC |
588 | | cmd | 622 | | (NAND_CMD_PAGEPROG << 8) |
623 | | NAND_CMD_SEQIN | ||
589 | | addr_cycle; | 624 | | addr_cycle; |
590 | break; | 625 | break; |
591 | 626 | ||
627 | case NAND_CMD_PARAM: | ||
628 | info->buf_count = 256; | ||
629 | info->ndcb0 |= NDCB0_CMD_TYPE(0) | ||
630 | | NDCB0_ADDR_CYC(1) | ||
631 | | NDCB0_LEN_OVRD | ||
632 | | command; | ||
633 | info->ndcb1 = (column & 0xFF); | ||
634 | info->ndcb3 = 256; | ||
635 | info->data_size = 256; | ||
636 | break; | ||
637 | |||
592 | case NAND_CMD_READID: | 638 | case NAND_CMD_READID: |
593 | cmd = host->cmdset->read_id; | ||
594 | info->buf_count = host->read_id_bytes; | 639 | info->buf_count = host->read_id_bytes; |
595 | info->ndcb0 |= NDCB0_CMD_TYPE(3) | 640 | info->ndcb0 |= NDCB0_CMD_TYPE(3) |
596 | | NDCB0_ADDR_CYC(1) | 641 | | NDCB0_ADDR_CYC(1) |
597 | | cmd; | 642 | | command; |
643 | info->ndcb1 = (column & 0xFF); | ||
598 | 644 | ||
599 | info->data_size = 8; | 645 | info->data_size = 8; |
600 | break; | 646 | break; |
601 | case NAND_CMD_STATUS: | 647 | case NAND_CMD_STATUS: |
602 | cmd = host->cmdset->read_status; | ||
603 | info->buf_count = 1; | 648 | info->buf_count = 1; |
604 | info->ndcb0 |= NDCB0_CMD_TYPE(4) | 649 | info->ndcb0 |= NDCB0_CMD_TYPE(4) |
605 | | NDCB0_ADDR_CYC(1) | 650 | | NDCB0_ADDR_CYC(1) |
606 | | cmd; | 651 | | command; |
607 | 652 | ||
608 | info->data_size = 8; | 653 | info->data_size = 8; |
609 | break; | 654 | break; |
610 | 655 | ||
611 | case NAND_CMD_ERASE1: | 656 | case NAND_CMD_ERASE1: |
612 | cmd = host->cmdset->erase; | ||
613 | info->ndcb0 |= NDCB0_CMD_TYPE(2) | 657 | info->ndcb0 |= NDCB0_CMD_TYPE(2) |
614 | | NDCB0_AUTO_RS | 658 | | NDCB0_AUTO_RS |
615 | | NDCB0_ADDR_CYC(3) | 659 | | NDCB0_ADDR_CYC(3) |
616 | | NDCB0_DBC | 660 | | NDCB0_DBC |
617 | | cmd; | 661 | | (NAND_CMD_ERASE2 << 8) |
662 | | NAND_CMD_ERASE1; | ||
618 | info->ndcb1 = page_addr; | 663 | info->ndcb1 = page_addr; |
619 | info->ndcb2 = 0; | 664 | info->ndcb2 = 0; |
620 | 665 | ||
621 | break; | 666 | break; |
622 | case NAND_CMD_RESET: | 667 | case NAND_CMD_RESET: |
623 | cmd = host->cmdset->reset; | ||
624 | info->ndcb0 |= NDCB0_CMD_TYPE(5) | 668 | info->ndcb0 |= NDCB0_CMD_TYPE(5) |
625 | | cmd; | 669 | | command; |
626 | 670 | ||
627 | break; | 671 | break; |
628 | 672 | ||
@@ -652,7 +696,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
652 | * "byte" address into a "word" address appropriate | 696 | * "byte" address into a "word" address appropriate |
653 | * for indexing a word-oriented device | 697 | * for indexing a word-oriented device |
654 | */ | 698 | */ |
655 | if (host->reg_ndcr & NDCR_DWIDTH_M) | 699 | if (info->reg_ndcr & NDCR_DWIDTH_M) |
656 | column /= 2; | 700 | column /= 2; |
657 | 701 | ||
658 | /* | 702 | /* |
@@ -662,8 +706,8 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
662 | */ | 706 | */ |
663 | if (info->cs != host->cs) { | 707 | if (info->cs != host->cs) { |
664 | info->cs = host->cs; | 708 | info->cs = host->cs; |
665 | nand_writel(info, NDTR0CS0, host->ndtr0cs0); | 709 | nand_writel(info, NDTR0CS0, info->ndtr0cs0); |
666 | nand_writel(info, NDTR1CS0, host->ndtr1cs0); | 710 | nand_writel(info, NDTR1CS0, info->ndtr1cs0); |
667 | } | 711 | } |
668 | 712 | ||
669 | info->state = STATE_PREPARED; | 713 | info->state = STATE_PREPARED; |
@@ -803,7 +847,7 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, | |||
803 | const struct pxa3xx_nand_flash *f) | 847 | const struct pxa3xx_nand_flash *f) |
804 | { | 848 | { |
805 | struct platform_device *pdev = info->pdev; | 849 | struct platform_device *pdev = info->pdev; |
806 | struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; | 850 | struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); |
807 | struct pxa3xx_nand_host *host = info->host[info->cs]; | 851 | struct pxa3xx_nand_host *host = info->host[info->cs]; |
808 | uint32_t ndcr = 0x0; /* enable all interrupts */ | 852 | uint32_t ndcr = 0x0; /* enable all interrupts */ |
809 | 853 | ||
@@ -818,7 +862,6 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, | |||
818 | } | 862 | } |
819 | 863 | ||
820 | /* calculate flash information */ | 864 | /* calculate flash information */ |
821 | host->cmdset = &default_cmdset; | ||
822 | host->page_size = f->page_size; | 865 | host->page_size = f->page_size; |
823 | host->read_id_bytes = (f->page_size == 2048) ? 4 : 2; | 866 | host->read_id_bytes = (f->page_size == 2048) ? 4 : 2; |
824 | 867 | ||
@@ -840,7 +883,7 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, | |||
840 | ndcr |= NDCR_RD_ID_CNT(host->read_id_bytes); | 883 | ndcr |= NDCR_RD_ID_CNT(host->read_id_bytes); |
841 | ndcr |= NDCR_SPARE_EN; /* enable spare by default */ | 884 | ndcr |= NDCR_SPARE_EN; /* enable spare by default */ |
842 | 885 | ||
843 | host->reg_ndcr = ndcr; | 886 | info->reg_ndcr = ndcr; |
844 | 887 | ||
845 | pxa3xx_nand_set_timing(host, f->timing); | 888 | pxa3xx_nand_set_timing(host, f->timing); |
846 | return 0; | 889 | return 0; |
@@ -863,12 +906,9 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) | |||
863 | host->read_id_bytes = 2; | 906 | host->read_id_bytes = 2; |
864 | } | 907 | } |
865 | 908 | ||
866 | host->reg_ndcr = ndcr & ~NDCR_INT_MASK; | 909 | info->reg_ndcr = ndcr & ~NDCR_INT_MASK; |
867 | host->cmdset = &default_cmdset; | 910 | info->ndtr0cs0 = nand_readl(info, NDTR0CS0); |
868 | 911 | info->ndtr1cs0 = nand_readl(info, NDTR1CS0); | |
869 | host->ndtr0cs0 = nand_readl(info, NDTR0CS0); | ||
870 | host->ndtr1cs0 = nand_readl(info, NDTR1CS0); | ||
871 | |||
872 | return 0; | 912 | return 0; |
873 | } | 913 | } |
874 | 914 | ||
@@ -878,6 +918,7 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) | |||
878 | */ | 918 | */ |
879 | #define MAX_BUFF_SIZE PAGE_SIZE | 919 | #define MAX_BUFF_SIZE PAGE_SIZE |
880 | 920 | ||
921 | #ifdef ARCH_HAS_DMA | ||
881 | static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) | 922 | static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) |
882 | { | 923 | { |
883 | struct platform_device *pdev = info->pdev; | 924 | struct platform_device *pdev = info->pdev; |
@@ -912,6 +953,32 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) | |||
912 | return 0; | 953 | return 0; |
913 | } | 954 | } |
914 | 955 | ||
956 | static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info) | ||
957 | { | ||
958 | struct platform_device *pdev = info->pdev; | ||
959 | if (use_dma) { | ||
960 | pxa_free_dma(info->data_dma_ch); | ||
961 | dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE, | ||
962 | info->data_buff, info->data_buff_phys); | ||
963 | } else { | ||
964 | kfree(info->data_buff); | ||
965 | } | ||
966 | } | ||
967 | #else | ||
968 | static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) | ||
969 | { | ||
970 | info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL); | ||
971 | if (info->data_buff == NULL) | ||
972 | return -ENOMEM; | ||
973 | return 0; | ||
974 | } | ||
975 | |||
976 | static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info) | ||
977 | { | ||
978 | kfree(info->data_buff); | ||
979 | } | ||
980 | #endif | ||
981 | |||
915 | static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info) | 982 | static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info) |
916 | { | 983 | { |
917 | struct mtd_info *mtd; | 984 | struct mtd_info *mtd; |
@@ -934,7 +1001,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) | |||
934 | struct pxa3xx_nand_host *host = mtd->priv; | 1001 | struct pxa3xx_nand_host *host = mtd->priv; |
935 | struct pxa3xx_nand_info *info = host->info_data; | 1002 | struct pxa3xx_nand_info *info = host->info_data; |
936 | struct platform_device *pdev = info->pdev; | 1003 | struct platform_device *pdev = info->pdev; |
937 | struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; | 1004 | struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); |
938 | struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL; | 1005 | struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL; |
939 | const struct pxa3xx_nand_flash *f = NULL; | 1006 | const struct pxa3xx_nand_flash *f = NULL; |
940 | struct nand_chip *chip = mtd->priv; | 1007 | struct nand_chip *chip = mtd->priv; |
@@ -1003,7 +1070,7 @@ KEEP_CONFIG: | |||
1003 | chip->ecc.size = host->page_size; | 1070 | chip->ecc.size = host->page_size; |
1004 | chip->ecc.strength = 1; | 1071 | chip->ecc.strength = 1; |
1005 | 1072 | ||
1006 | if (host->reg_ndcr & NDCR_DWIDTH_M) | 1073 | if (info->reg_ndcr & NDCR_DWIDTH_M) |
1007 | chip->options |= NAND_BUSWIDTH_16; | 1074 | chip->options |= NAND_BUSWIDTH_16; |
1008 | 1075 | ||
1009 | if (nand_scan_ident(mtd, 1, def)) | 1076 | if (nand_scan_ident(mtd, 1, def)) |
@@ -1019,8 +1086,6 @@ KEEP_CONFIG: | |||
1019 | host->row_addr_cycles = 3; | 1086 | host->row_addr_cycles = 3; |
1020 | else | 1087 | else |
1021 | host->row_addr_cycles = 2; | 1088 | host->row_addr_cycles = 2; |
1022 | |||
1023 | mtd->name = mtd_names[0]; | ||
1024 | return nand_scan_tail(mtd); | 1089 | return nand_scan_tail(mtd); |
1025 | } | 1090 | } |
1026 | 1091 | ||
@@ -1034,13 +1099,11 @@ static int alloc_nand_resource(struct platform_device *pdev) | |||
1034 | struct resource *r; | 1099 | struct resource *r; |
1035 | int ret, irq, cs; | 1100 | int ret, irq, cs; |
1036 | 1101 | ||
1037 | pdata = pdev->dev.platform_data; | 1102 | pdata = dev_get_platdata(&pdev->dev); |
1038 | info = kzalloc(sizeof(*info) + (sizeof(*mtd) + | 1103 | info = devm_kzalloc(&pdev->dev, sizeof(*info) + (sizeof(*mtd) + |
1039 | sizeof(*host)) * pdata->num_cs, GFP_KERNEL); | 1104 | sizeof(*host)) * pdata->num_cs, GFP_KERNEL); |
1040 | if (!info) { | 1105 | if (!info) |
1041 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
1042 | return -ENOMEM; | 1106 | return -ENOMEM; |
1043 | } | ||
1044 | 1107 | ||
1045 | info->pdev = pdev; | 1108 | info->pdev = pdev; |
1046 | for (cs = 0; cs < pdata->num_cs; cs++) { | 1109 | for (cs = 0; cs < pdata->num_cs; cs++) { |
@@ -1069,72 +1132,64 @@ static int alloc_nand_resource(struct platform_device *pdev) | |||
1069 | 1132 | ||
1070 | spin_lock_init(&chip->controller->lock); | 1133 | spin_lock_init(&chip->controller->lock); |
1071 | init_waitqueue_head(&chip->controller->wq); | 1134 | init_waitqueue_head(&chip->controller->wq); |
1072 | info->clk = clk_get(&pdev->dev, NULL); | 1135 | info->clk = devm_clk_get(&pdev->dev, NULL); |
1073 | if (IS_ERR(info->clk)) { | 1136 | if (IS_ERR(info->clk)) { |
1074 | dev_err(&pdev->dev, "failed to get nand clock\n"); | 1137 | dev_err(&pdev->dev, "failed to get nand clock\n"); |
1075 | ret = PTR_ERR(info->clk); | 1138 | return PTR_ERR(info->clk); |
1076 | goto fail_free_mtd; | ||
1077 | } | 1139 | } |
1078 | clk_enable(info->clk); | 1140 | ret = clk_prepare_enable(info->clk); |
1079 | 1141 | if (ret < 0) | |
1080 | /* | 1142 | return ret; |
1081 | * This is a dirty hack to make this driver work from devicetree | ||
1082 | * bindings. It can be removed once we have a prober DMA controller | ||
1083 | * framework for DT. | ||
1084 | */ | ||
1085 | if (pdev->dev.of_node && cpu_is_pxa3xx()) { | ||
1086 | info->drcmr_dat = 97; | ||
1087 | info->drcmr_cmd = 99; | ||
1088 | } else { | ||
1089 | r = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
1090 | if (r == NULL) { | ||
1091 | dev_err(&pdev->dev, "no resource defined for data DMA\n"); | ||
1092 | ret = -ENXIO; | ||
1093 | goto fail_put_clk; | ||
1094 | } | ||
1095 | info->drcmr_dat = r->start; | ||
1096 | 1143 | ||
1097 | r = platform_get_resource(pdev, IORESOURCE_DMA, 1); | 1144 | if (use_dma) { |
1098 | if (r == NULL) { | 1145 | /* |
1099 | dev_err(&pdev->dev, "no resource defined for command DMA\n"); | 1146 | * This is a dirty hack to make this driver work from |
1100 | ret = -ENXIO; | 1147 | * devicetree bindings. It can be removed once we have |
1101 | goto fail_put_clk; | 1148 | * a prober DMA controller framework for DT. |
1149 | */ | ||
1150 | if (pdev->dev.of_node && | ||
1151 | of_machine_is_compatible("marvell,pxa3xx")) { | ||
1152 | info->drcmr_dat = 97; | ||
1153 | info->drcmr_cmd = 99; | ||
1154 | } else { | ||
1155 | r = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
1156 | if (r == NULL) { | ||
1157 | dev_err(&pdev->dev, | ||
1158 | "no resource defined for data DMA\n"); | ||
1159 | ret = -ENXIO; | ||
1160 | goto fail_disable_clk; | ||
1161 | } | ||
1162 | info->drcmr_dat = r->start; | ||
1163 | |||
1164 | r = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
1165 | if (r == NULL) { | ||
1166 | dev_err(&pdev->dev, | ||
1167 | "no resource defined for cmd DMA\n"); | ||
1168 | ret = -ENXIO; | ||
1169 | goto fail_disable_clk; | ||
1170 | } | ||
1171 | info->drcmr_cmd = r->start; | ||
1102 | } | 1172 | } |
1103 | info->drcmr_cmd = r->start; | ||
1104 | } | 1173 | } |
1105 | 1174 | ||
1106 | irq = platform_get_irq(pdev, 0); | 1175 | irq = platform_get_irq(pdev, 0); |
1107 | if (irq < 0) { | 1176 | if (irq < 0) { |
1108 | dev_err(&pdev->dev, "no IRQ resource defined\n"); | 1177 | dev_err(&pdev->dev, "no IRQ resource defined\n"); |
1109 | ret = -ENXIO; | 1178 | ret = -ENXIO; |
1110 | goto fail_put_clk; | 1179 | goto fail_disable_clk; |
1111 | } | 1180 | } |
1112 | 1181 | ||
1113 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1182 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1114 | if (r == NULL) { | 1183 | info->mmio_base = devm_ioremap_resource(&pdev->dev, r); |
1115 | dev_err(&pdev->dev, "no IO memory resource defined\n"); | 1184 | if (IS_ERR(info->mmio_base)) { |
1116 | ret = -ENODEV; | 1185 | ret = PTR_ERR(info->mmio_base); |
1117 | goto fail_put_clk; | 1186 | goto fail_disable_clk; |
1118 | } | ||
1119 | |||
1120 | r = request_mem_region(r->start, resource_size(r), pdev->name); | ||
1121 | if (r == NULL) { | ||
1122 | dev_err(&pdev->dev, "failed to request memory resource\n"); | ||
1123 | ret = -EBUSY; | ||
1124 | goto fail_put_clk; | ||
1125 | } | ||
1126 | |||
1127 | info->mmio_base = ioremap(r->start, resource_size(r)); | ||
1128 | if (info->mmio_base == NULL) { | ||
1129 | dev_err(&pdev->dev, "ioremap() failed\n"); | ||
1130 | ret = -ENODEV; | ||
1131 | goto fail_free_res; | ||
1132 | } | 1187 | } |
1133 | info->mmio_phys = r->start; | 1188 | info->mmio_phys = r->start; |
1134 | 1189 | ||
1135 | ret = pxa3xx_nand_init_buff(info); | 1190 | ret = pxa3xx_nand_init_buff(info); |
1136 | if (ret) | 1191 | if (ret) |
1137 | goto fail_free_io; | 1192 | goto fail_disable_clk; |
1138 | 1193 | ||
1139 | /* initialize all interrupts to be disabled */ | 1194 | /* initialize all interrupts to be disabled */ |
1140 | disable_int(info, NDSR_MASK); | 1195 | disable_int(info, NDSR_MASK); |
@@ -1152,21 +1207,9 @@ static int alloc_nand_resource(struct platform_device *pdev) | |||
1152 | 1207 | ||
1153 | fail_free_buf: | 1208 | fail_free_buf: |
1154 | free_irq(irq, info); | 1209 | free_irq(irq, info); |
1155 | if (use_dma) { | 1210 | pxa3xx_nand_free_buff(info); |
1156 | pxa_free_dma(info->data_dma_ch); | 1211 | fail_disable_clk: |
1157 | dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE, | 1212 | clk_disable_unprepare(info->clk); |
1158 | info->data_buff, info->data_buff_phys); | ||
1159 | } else | ||
1160 | kfree(info->data_buff); | ||
1161 | fail_free_io: | ||
1162 | iounmap(info->mmio_base); | ||
1163 | fail_free_res: | ||
1164 | release_mem_region(r->start, resource_size(r)); | ||
1165 | fail_put_clk: | ||
1166 | clk_disable(info->clk); | ||
1167 | clk_put(info->clk); | ||
1168 | fail_free_mtd: | ||
1169 | kfree(info); | ||
1170 | return ret; | 1213 | return ret; |
1171 | } | 1214 | } |
1172 | 1215 | ||
@@ -1174,44 +1217,48 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) | |||
1174 | { | 1217 | { |
1175 | struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); | 1218 | struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); |
1176 | struct pxa3xx_nand_platform_data *pdata; | 1219 | struct pxa3xx_nand_platform_data *pdata; |
1177 | struct resource *r; | ||
1178 | int irq, cs; | 1220 | int irq, cs; |
1179 | 1221 | ||
1180 | if (!info) | 1222 | if (!info) |
1181 | return 0; | 1223 | return 0; |
1182 | 1224 | ||
1183 | pdata = pdev->dev.platform_data; | 1225 | pdata = dev_get_platdata(&pdev->dev); |
1184 | platform_set_drvdata(pdev, NULL); | ||
1185 | 1226 | ||
1186 | irq = platform_get_irq(pdev, 0); | 1227 | irq = platform_get_irq(pdev, 0); |
1187 | if (irq >= 0) | 1228 | if (irq >= 0) |
1188 | free_irq(irq, info); | 1229 | free_irq(irq, info); |
1189 | if (use_dma) { | 1230 | pxa3xx_nand_free_buff(info); |
1190 | pxa_free_dma(info->data_dma_ch); | ||
1191 | dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE, | ||
1192 | info->data_buff, info->data_buff_phys); | ||
1193 | } else | ||
1194 | kfree(info->data_buff); | ||
1195 | |||
1196 | iounmap(info->mmio_base); | ||
1197 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1198 | release_mem_region(r->start, resource_size(r)); | ||
1199 | 1231 | ||
1200 | clk_disable(info->clk); | 1232 | clk_disable_unprepare(info->clk); |
1201 | clk_put(info->clk); | ||
1202 | 1233 | ||
1203 | for (cs = 0; cs < pdata->num_cs; cs++) | 1234 | for (cs = 0; cs < pdata->num_cs; cs++) |
1204 | nand_release(info->host[cs]->mtd); | 1235 | nand_release(info->host[cs]->mtd); |
1205 | kfree(info); | ||
1206 | return 0; | 1236 | return 0; |
1207 | } | 1237 | } |
1208 | 1238 | ||
1209 | #ifdef CONFIG_OF | 1239 | #ifdef CONFIG_OF |
1210 | static struct of_device_id pxa3xx_nand_dt_ids[] = { | 1240 | static struct of_device_id pxa3xx_nand_dt_ids[] = { |
1211 | { .compatible = "marvell,pxa3xx-nand" }, | 1241 | { |
1242 | .compatible = "marvell,pxa3xx-nand", | ||
1243 | .data = (void *)PXA3XX_NAND_VARIANT_PXA, | ||
1244 | }, | ||
1245 | { | ||
1246 | .compatible = "marvell,armada370-nand", | ||
1247 | .data = (void *)PXA3XX_NAND_VARIANT_ARMADA370, | ||
1248 | }, | ||
1212 | {} | 1249 | {} |
1213 | }; | 1250 | }; |
1214 | MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids); | 1251 | MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids); |
1252 | |||
1253 | static enum pxa3xx_nand_variant | ||
1254 | pxa3xx_nand_get_variant(struct platform_device *pdev) | ||
1255 | { | ||
1256 | const struct of_device_id *of_id = | ||
1257 | of_match_device(pxa3xx_nand_dt_ids, &pdev->dev); | ||
1258 | if (!of_id) | ||
1259 | return PXA3XX_NAND_VARIANT_PXA; | ||
1260 | return (enum pxa3xx_nand_variant)of_id->data; | ||
1261 | } | ||
1215 | 1262 | ||
1216 | static int pxa3xx_nand_probe_dt(struct platform_device *pdev) | 1263 | static int pxa3xx_nand_probe_dt(struct platform_device *pdev) |
1217 | { | 1264 | { |
@@ -1251,11 +1298,18 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
1251 | struct pxa3xx_nand_info *info; | 1298 | struct pxa3xx_nand_info *info; |
1252 | int ret, cs, probe_success; | 1299 | int ret, cs, probe_success; |
1253 | 1300 | ||
1301 | #ifndef ARCH_HAS_DMA | ||
1302 | if (use_dma) { | ||
1303 | use_dma = 0; | ||
1304 | dev_warn(&pdev->dev, | ||
1305 | "This platform can't do DMA on this device\n"); | ||
1306 | } | ||
1307 | #endif | ||
1254 | ret = pxa3xx_nand_probe_dt(pdev); | 1308 | ret = pxa3xx_nand_probe_dt(pdev); |
1255 | if (ret) | 1309 | if (ret) |
1256 | return ret; | 1310 | return ret; |
1257 | 1311 | ||
1258 | pdata = pdev->dev.platform_data; | 1312 | pdata = dev_get_platdata(&pdev->dev); |
1259 | if (!pdata) { | 1313 | if (!pdata) { |
1260 | dev_err(&pdev->dev, "no platform data defined\n"); | 1314 | dev_err(&pdev->dev, "no platform data defined\n"); |
1261 | return -ENODEV; | 1315 | return -ENODEV; |
@@ -1268,10 +1322,14 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
1268 | } | 1322 | } |
1269 | 1323 | ||
1270 | info = platform_get_drvdata(pdev); | 1324 | info = platform_get_drvdata(pdev); |
1325 | info->variant = pxa3xx_nand_get_variant(pdev); | ||
1271 | probe_success = 0; | 1326 | probe_success = 0; |
1272 | for (cs = 0; cs < pdata->num_cs; cs++) { | 1327 | for (cs = 0; cs < pdata->num_cs; cs++) { |
1328 | struct mtd_info *mtd = info->host[cs]->mtd; | ||
1329 | |||
1330 | mtd->name = pdev->name; | ||
1273 | info->cs = cs; | 1331 | info->cs = cs; |
1274 | ret = pxa3xx_nand_scan(info->host[cs]->mtd); | 1332 | ret = pxa3xx_nand_scan(mtd); |
1275 | if (ret) { | 1333 | if (ret) { |
1276 | dev_warn(&pdev->dev, "failed to scan nand at cs %d\n", | 1334 | dev_warn(&pdev->dev, "failed to scan nand at cs %d\n", |
1277 | cs); | 1335 | cs); |
@@ -1279,7 +1337,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
1279 | } | 1337 | } |
1280 | 1338 | ||
1281 | ppdata.of_node = pdev->dev.of_node; | 1339 | ppdata.of_node = pdev->dev.of_node; |
1282 | ret = mtd_device_parse_register(info->host[cs]->mtd, NULL, | 1340 | ret = mtd_device_parse_register(mtd, NULL, |
1283 | &ppdata, pdata->parts[cs], | 1341 | &ppdata, pdata->parts[cs], |
1284 | pdata->nr_parts[cs]); | 1342 | pdata->nr_parts[cs]); |
1285 | if (!ret) | 1343 | if (!ret) |
@@ -1302,7 +1360,7 @@ static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state) | |||
1302 | struct mtd_info *mtd; | 1360 | struct mtd_info *mtd; |
1303 | int cs; | 1361 | int cs; |
1304 | 1362 | ||
1305 | pdata = pdev->dev.platform_data; | 1363 | pdata = dev_get_platdata(&pdev->dev); |
1306 | if (info->state) { | 1364 | if (info->state) { |
1307 | dev_err(&pdev->dev, "driver busy, state = %d\n", info->state); | 1365 | dev_err(&pdev->dev, "driver busy, state = %d\n", info->state); |
1308 | return -EAGAIN; | 1366 | return -EAGAIN; |
@@ -1323,7 +1381,7 @@ static int pxa3xx_nand_resume(struct platform_device *pdev) | |||
1323 | struct mtd_info *mtd; | 1381 | struct mtd_info *mtd; |
1324 | int cs; | 1382 | int cs; |
1325 | 1383 | ||
1326 | pdata = pdev->dev.platform_data; | 1384 | pdata = dev_get_platdata(&pdev->dev); |
1327 | /* We don't want to handle interrupt without calling mtd routine */ | 1385 | /* We don't want to handle interrupt without calling mtd routine */ |
1328 | disable_int(info, NDCR_INT_MASK); | 1386 | disable_int(info, NDCR_INT_MASK); |
1329 | 1387 | ||
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index 4495f8551fa0..9dcf02d22aa8 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c | |||
@@ -229,7 +229,7 @@ static void r852_do_dma(struct r852_device *dev, uint8_t *buf, int do_read) | |||
229 | /* | 229 | /* |
230 | * Program data lines of the nand chip to send data to it | 230 | * Program data lines of the nand chip to send data to it |
231 | */ | 231 | */ |
232 | void r852_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | 232 | static void r852_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) |
233 | { | 233 | { |
234 | struct r852_device *dev = r852_get_dev(mtd); | 234 | struct r852_device *dev = r852_get_dev(mtd); |
235 | uint32_t reg; | 235 | uint32_t reg; |
@@ -261,7 +261,7 @@ void r852_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | |||
261 | /* | 261 | /* |
262 | * Read data lines of the nand chip to retrieve data | 262 | * Read data lines of the nand chip to retrieve data |
263 | */ | 263 | */ |
264 | void r852_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | 264 | static void r852_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) |
265 | { | 265 | { |
266 | struct r852_device *dev = r852_get_dev(mtd); | 266 | struct r852_device *dev = r852_get_dev(mtd); |
267 | uint32_t reg; | 267 | uint32_t reg; |
@@ -312,7 +312,7 @@ static uint8_t r852_read_byte(struct mtd_info *mtd) | |||
312 | /* | 312 | /* |
313 | * Control several chip lines & send commands | 313 | * Control several chip lines & send commands |
314 | */ | 314 | */ |
315 | void r852_cmdctl(struct mtd_info *mtd, int dat, unsigned int ctrl) | 315 | static void r852_cmdctl(struct mtd_info *mtd, int dat, unsigned int ctrl) |
316 | { | 316 | { |
317 | struct r852_device *dev = r852_get_dev(mtd); | 317 | struct r852_device *dev = r852_get_dev(mtd); |
318 | 318 | ||
@@ -357,7 +357,7 @@ void r852_cmdctl(struct mtd_info *mtd, int dat, unsigned int ctrl) | |||
357 | * Wait till card is ready. | 357 | * Wait till card is ready. |
358 | * based on nand_wait, but returns errors on DMA error | 358 | * based on nand_wait, but returns errors on DMA error |
359 | */ | 359 | */ |
360 | int r852_wait(struct mtd_info *mtd, struct nand_chip *chip) | 360 | static int r852_wait(struct mtd_info *mtd, struct nand_chip *chip) |
361 | { | 361 | { |
362 | struct r852_device *dev = chip->priv; | 362 | struct r852_device *dev = chip->priv; |
363 | 363 | ||
@@ -386,7 +386,7 @@ int r852_wait(struct mtd_info *mtd, struct nand_chip *chip) | |||
386 | * Check if card is ready | 386 | * Check if card is ready |
387 | */ | 387 | */ |
388 | 388 | ||
389 | int r852_ready(struct mtd_info *mtd) | 389 | static int r852_ready(struct mtd_info *mtd) |
390 | { | 390 | { |
391 | struct r852_device *dev = r852_get_dev(mtd); | 391 | struct r852_device *dev = r852_get_dev(mtd); |
392 | return !(r852_read_reg(dev, R852_CARD_STA) & R852_CARD_STA_BUSY); | 392 | return !(r852_read_reg(dev, R852_CARD_STA) & R852_CARD_STA_BUSY); |
@@ -397,7 +397,7 @@ int r852_ready(struct mtd_info *mtd) | |||
397 | * Set ECC engine mode | 397 | * Set ECC engine mode |
398 | */ | 398 | */ |
399 | 399 | ||
400 | void r852_ecc_hwctl(struct mtd_info *mtd, int mode) | 400 | static void r852_ecc_hwctl(struct mtd_info *mtd, int mode) |
401 | { | 401 | { |
402 | struct r852_device *dev = r852_get_dev(mtd); | 402 | struct r852_device *dev = r852_get_dev(mtd); |
403 | 403 | ||
@@ -429,7 +429,7 @@ void r852_ecc_hwctl(struct mtd_info *mtd, int mode) | |||
429 | * Calculate ECC, only used for writes | 429 | * Calculate ECC, only used for writes |
430 | */ | 430 | */ |
431 | 431 | ||
432 | int r852_ecc_calculate(struct mtd_info *mtd, const uint8_t *dat, | 432 | static int r852_ecc_calculate(struct mtd_info *mtd, const uint8_t *dat, |
433 | uint8_t *ecc_code) | 433 | uint8_t *ecc_code) |
434 | { | 434 | { |
435 | struct r852_device *dev = r852_get_dev(mtd); | 435 | struct r852_device *dev = r852_get_dev(mtd); |
@@ -461,7 +461,7 @@ int r852_ecc_calculate(struct mtd_info *mtd, const uint8_t *dat, | |||
461 | * Correct the data using ECC, hw did almost everything for us | 461 | * Correct the data using ECC, hw did almost everything for us |
462 | */ | 462 | */ |
463 | 463 | ||
464 | int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat, | 464 | static int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat, |
465 | uint8_t *read_ecc, uint8_t *calc_ecc) | 465 | uint8_t *read_ecc, uint8_t *calc_ecc) |
466 | { | 466 | { |
467 | uint16_t ecc_reg; | 467 | uint16_t ecc_reg; |
@@ -529,7 +529,7 @@ static int r852_read_oob(struct mtd_info *mtd, struct nand_chip *chip, | |||
529 | * Start the nand engine | 529 | * Start the nand engine |
530 | */ | 530 | */ |
531 | 531 | ||
532 | void r852_engine_enable(struct r852_device *dev) | 532 | static void r852_engine_enable(struct r852_device *dev) |
533 | { | 533 | { |
534 | if (r852_read_reg_dword(dev, R852_HW) & R852_HW_UNKNOWN) { | 534 | if (r852_read_reg_dword(dev, R852_HW) & R852_HW_UNKNOWN) { |
535 | r852_write_reg(dev, R852_CTL, R852_CTL_RESET | R852_CTL_ON); | 535 | r852_write_reg(dev, R852_CTL, R852_CTL_RESET | R852_CTL_ON); |
@@ -547,7 +547,7 @@ void r852_engine_enable(struct r852_device *dev) | |||
547 | * Stop the nand engine | 547 | * Stop the nand engine |
548 | */ | 548 | */ |
549 | 549 | ||
550 | void r852_engine_disable(struct r852_device *dev) | 550 | static void r852_engine_disable(struct r852_device *dev) |
551 | { | 551 | { |
552 | r852_write_reg_dword(dev, R852_HW, 0); | 552 | r852_write_reg_dword(dev, R852_HW, 0); |
553 | r852_write_reg(dev, R852_CTL, R852_CTL_RESET); | 553 | r852_write_reg(dev, R852_CTL, R852_CTL_RESET); |
@@ -557,7 +557,7 @@ void r852_engine_disable(struct r852_device *dev) | |||
557 | * Test if card is present | 557 | * Test if card is present |
558 | */ | 558 | */ |
559 | 559 | ||
560 | void r852_card_update_present(struct r852_device *dev) | 560 | static void r852_card_update_present(struct r852_device *dev) |
561 | { | 561 | { |
562 | unsigned long flags; | 562 | unsigned long flags; |
563 | uint8_t reg; | 563 | uint8_t reg; |
@@ -572,7 +572,7 @@ void r852_card_update_present(struct r852_device *dev) | |||
572 | * Update card detection IRQ state according to current card state | 572 | * Update card detection IRQ state according to current card state |
573 | * which is read in r852_card_update_present | 573 | * which is read in r852_card_update_present |
574 | */ | 574 | */ |
575 | void r852_update_card_detect(struct r852_device *dev) | 575 | static void r852_update_card_detect(struct r852_device *dev) |
576 | { | 576 | { |
577 | int card_detect_reg = r852_read_reg(dev, R852_CARD_IRQ_ENABLE); | 577 | int card_detect_reg = r852_read_reg(dev, R852_CARD_IRQ_ENABLE); |
578 | dev->card_unstable = 0; | 578 | dev->card_unstable = 0; |
@@ -586,8 +586,8 @@ void r852_update_card_detect(struct r852_device *dev) | |||
586 | r852_write_reg(dev, R852_CARD_IRQ_ENABLE, card_detect_reg); | 586 | r852_write_reg(dev, R852_CARD_IRQ_ENABLE, card_detect_reg); |
587 | } | 587 | } |
588 | 588 | ||
589 | ssize_t r852_media_type_show(struct device *sys_dev, | 589 | static ssize_t r852_media_type_show(struct device *sys_dev, |
590 | struct device_attribute *attr, char *buf) | 590 | struct device_attribute *attr, char *buf) |
591 | { | 591 | { |
592 | struct mtd_info *mtd = container_of(sys_dev, struct mtd_info, dev); | 592 | struct mtd_info *mtd = container_of(sys_dev, struct mtd_info, dev); |
593 | struct r852_device *dev = r852_get_dev(mtd); | 593 | struct r852_device *dev = r852_get_dev(mtd); |
@@ -597,11 +597,11 @@ ssize_t r852_media_type_show(struct device *sys_dev, | |||
597 | return strlen(data); | 597 | return strlen(data); |
598 | } | 598 | } |
599 | 599 | ||
600 | DEVICE_ATTR(media_type, S_IRUGO, r852_media_type_show, NULL); | 600 | static DEVICE_ATTR(media_type, S_IRUGO, r852_media_type_show, NULL); |
601 | 601 | ||
602 | 602 | ||
603 | /* Detect properties of card in slot */ | 603 | /* Detect properties of card in slot */ |
604 | void r852_update_media_status(struct r852_device *dev) | 604 | static void r852_update_media_status(struct r852_device *dev) |
605 | { | 605 | { |
606 | uint8_t reg; | 606 | uint8_t reg; |
607 | unsigned long flags; | 607 | unsigned long flags; |
@@ -630,7 +630,7 @@ void r852_update_media_status(struct r852_device *dev) | |||
630 | * Register the nand device | 630 | * Register the nand device |
631 | * Called when the card is detected | 631 | * Called when the card is detected |
632 | */ | 632 | */ |
633 | int r852_register_nand_device(struct r852_device *dev) | 633 | static int r852_register_nand_device(struct r852_device *dev) |
634 | { | 634 | { |
635 | dev->mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); | 635 | dev->mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); |
636 | 636 | ||
@@ -668,7 +668,7 @@ error1: | |||
668 | * Unregister the card | 668 | * Unregister the card |
669 | */ | 669 | */ |
670 | 670 | ||
671 | void r852_unregister_nand_device(struct r852_device *dev) | 671 | static void r852_unregister_nand_device(struct r852_device *dev) |
672 | { | 672 | { |
673 | if (!dev->card_registred) | 673 | if (!dev->card_registred) |
674 | return; | 674 | return; |
@@ -682,7 +682,7 @@ void r852_unregister_nand_device(struct r852_device *dev) | |||
682 | } | 682 | } |
683 | 683 | ||
684 | /* Card state updater */ | 684 | /* Card state updater */ |
685 | void r852_card_detect_work(struct work_struct *work) | 685 | static void r852_card_detect_work(struct work_struct *work) |
686 | { | 686 | { |
687 | struct r852_device *dev = | 687 | struct r852_device *dev = |
688 | container_of(work, struct r852_device, card_detect_work.work); | 688 | container_of(work, struct r852_device, card_detect_work.work); |
@@ -821,7 +821,7 @@ out: | |||
821 | return ret; | 821 | return ret; |
822 | } | 822 | } |
823 | 823 | ||
824 | int r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) | 824 | static int r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) |
825 | { | 825 | { |
826 | int error; | 826 | int error; |
827 | struct nand_chip *chip; | 827 | struct nand_chip *chip; |
@@ -961,7 +961,7 @@ error1: | |||
961 | return error; | 961 | return error; |
962 | } | 962 | } |
963 | 963 | ||
964 | void r852_remove(struct pci_dev *pci_dev) | 964 | static void r852_remove(struct pci_dev *pci_dev) |
965 | { | 965 | { |
966 | struct r852_device *dev = pci_get_drvdata(pci_dev); | 966 | struct r852_device *dev = pci_get_drvdata(pci_dev); |
967 | 967 | ||
@@ -992,7 +992,7 @@ void r852_remove(struct pci_dev *pci_dev) | |||
992 | pci_disable_device(pci_dev); | 992 | pci_disable_device(pci_dev); |
993 | } | 993 | } |
994 | 994 | ||
995 | void r852_shutdown(struct pci_dev *pci_dev) | 995 | static void r852_shutdown(struct pci_dev *pci_dev) |
996 | { | 996 | { |
997 | struct r852_device *dev = pci_get_drvdata(pci_dev); | 997 | struct r852_device *dev = pci_get_drvdata(pci_dev); |
998 | 998 | ||
@@ -1002,7 +1002,7 @@ void r852_shutdown(struct pci_dev *pci_dev) | |||
1002 | pci_disable_device(pci_dev); | 1002 | pci_disable_device(pci_dev); |
1003 | } | 1003 | } |
1004 | 1004 | ||
1005 | #ifdef CONFIG_PM | 1005 | #ifdef CONFIG_PM_SLEEP |
1006 | static int r852_suspend(struct device *device) | 1006 | static int r852_suspend(struct device *device) |
1007 | { | 1007 | { |
1008 | struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); | 1008 | struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); |
@@ -1055,9 +1055,6 @@ static int r852_resume(struct device *device) | |||
1055 | r852_update_card_detect(dev); | 1055 | r852_update_card_detect(dev); |
1056 | return 0; | 1056 | return 0; |
1057 | } | 1057 | } |
1058 | #else | ||
1059 | #define r852_suspend NULL | ||
1060 | #define r852_resume NULL | ||
1061 | #endif | 1058 | #endif |
1062 | 1059 | ||
1063 | static const struct pci_device_id r852_pci_id_tbl[] = { | 1060 | static const struct pci_device_id r852_pci_id_tbl[] = { |
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index d65afd23e171..d65cbe903d40 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c | |||
@@ -150,7 +150,7 @@ static struct s3c2410_nand_info *to_nand_info(struct platform_device *dev) | |||
150 | 150 | ||
151 | static struct s3c2410_platform_nand *to_nand_plat(struct platform_device *dev) | 151 | static struct s3c2410_platform_nand *to_nand_plat(struct platform_device *dev) |
152 | { | 152 | { |
153 | return dev->dev.platform_data; | 153 | return dev_get_platdata(&dev->dev); |
154 | } | 154 | } |
155 | 155 | ||
156 | static inline int allow_clk_suspend(struct s3c2410_nand_info *info) | 156 | static inline int allow_clk_suspend(struct s3c2410_nand_info *info) |
@@ -697,8 +697,6 @@ static int s3c24xx_nand_remove(struct platform_device *pdev) | |||
697 | { | 697 | { |
698 | struct s3c2410_nand_info *info = to_nand_info(pdev); | 698 | struct s3c2410_nand_info *info = to_nand_info(pdev); |
699 | 699 | ||
700 | platform_set_drvdata(pdev, NULL); | ||
701 | |||
702 | if (info == NULL) | 700 | if (info == NULL) |
703 | return 0; | 701 | return 0; |
704 | 702 | ||
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c index e57e18e8c289..a3c84ebbe392 100644 --- a/drivers/mtd/nand/sh_flctl.c +++ b/drivers/mtd/nand/sh_flctl.c | |||
@@ -137,7 +137,7 @@ static void flctl_setup_dma(struct sh_flctl *flctl) | |||
137 | dma_cap_mask_t mask; | 137 | dma_cap_mask_t mask; |
138 | struct dma_slave_config cfg; | 138 | struct dma_slave_config cfg; |
139 | struct platform_device *pdev = flctl->pdev; | 139 | struct platform_device *pdev = flctl->pdev; |
140 | struct sh_flctl_platform_data *pdata = pdev->dev.platform_data; | 140 | struct sh_flctl_platform_data *pdata = dev_get_platdata(&pdev->dev); |
141 | int ret; | 141 | int ret; |
142 | 142 | ||
143 | if (!pdata) | 143 | if (!pdata) |
@@ -1131,7 +1131,7 @@ static int flctl_probe(struct platform_device *pdev) | |||
1131 | if (pdev->dev.of_node) | 1131 | if (pdev->dev.of_node) |
1132 | pdata = flctl_parse_dt(&pdev->dev); | 1132 | pdata = flctl_parse_dt(&pdev->dev); |
1133 | else | 1133 | else |
1134 | pdata = pdev->dev.platform_data; | 1134 | pdata = dev_get_platdata(&pdev->dev); |
1135 | 1135 | ||
1136 | if (!pdata) { | 1136 | if (!pdata) { |
1137 | dev_err(&pdev->dev, "no setup data defined\n"); | 1137 | dev_err(&pdev->dev, "no setup data defined\n"); |
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 127bc4271821..87908d760feb 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c | |||
@@ -112,7 +112,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev) | |||
112 | struct resource *r; | 112 | struct resource *r; |
113 | int err = 0; | 113 | int err = 0; |
114 | struct sharpsl_nand *sharpsl; | 114 | struct sharpsl_nand *sharpsl; |
115 | struct sharpsl_nand_platform_data *data = pdev->dev.platform_data; | 115 | struct sharpsl_nand_platform_data *data = dev_get_platdata(&pdev->dev); |
116 | 116 | ||
117 | if (!data) { | 117 | if (!data) { |
118 | dev_err(&pdev->dev, "no platform data!\n"); | 118 | dev_err(&pdev->dev, "no platform data!\n"); |
@@ -194,7 +194,6 @@ err_add: | |||
194 | nand_release(&sharpsl->mtd); | 194 | nand_release(&sharpsl->mtd); |
195 | 195 | ||
196 | err_scan: | 196 | err_scan: |
197 | platform_set_drvdata(pdev, NULL); | ||
198 | iounmap(sharpsl->io); | 197 | iounmap(sharpsl->io); |
199 | err_ioremap: | 198 | err_ioremap: |
200 | err_get_res: | 199 | err_get_res: |
@@ -212,8 +211,6 @@ static int sharpsl_nand_remove(struct platform_device *pdev) | |||
212 | /* Release resources, unregister device */ | 211 | /* Release resources, unregister device */ |
213 | nand_release(&sharpsl->mtd); | 212 | nand_release(&sharpsl->mtd); |
214 | 213 | ||
215 | platform_set_drvdata(pdev, NULL); | ||
216 | |||
217 | iounmap(sharpsl->io); | 214 | iounmap(sharpsl->io); |
218 | 215 | ||
219 | /* Free the MTD device structure */ | 216 | /* Free the MTD device structure */ |
diff --git a/drivers/mtd/nand/sm_common.c b/drivers/mtd/nand/sm_common.c index e8181edebddd..e06b5e5d3287 100644 --- a/drivers/mtd/nand/sm_common.c +++ b/drivers/mtd/nand/sm_common.c | |||
@@ -42,7 +42,7 @@ static int sm_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
42 | { | 42 | { |
43 | struct mtd_oob_ops ops; | 43 | struct mtd_oob_ops ops; |
44 | struct sm_oob oob; | 44 | struct sm_oob oob; |
45 | int ret, error = 0; | 45 | int ret; |
46 | 46 | ||
47 | memset(&oob, -1, SM_OOB_SIZE); | 47 | memset(&oob, -1, SM_OOB_SIZE); |
48 | oob.block_status = 0x0F; | 48 | oob.block_status = 0x0F; |
@@ -61,11 +61,10 @@ static int sm_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
61 | printk(KERN_NOTICE | 61 | printk(KERN_NOTICE |
62 | "sm_common: can't mark sector at %i as bad\n", | 62 | "sm_common: can't mark sector at %i as bad\n", |
63 | (int)ofs); | 63 | (int)ofs); |
64 | error = -EIO; | 64 | return -EIO; |
65 | } else | 65 | } |
66 | mtd->ecc_stats.badblocks++; | ||
67 | 66 | ||
68 | return error; | 67 | return 0; |
69 | } | 68 | } |
70 | 69 | ||
71 | static struct nand_flash_dev nand_smartmedia_flash_ids[] = { | 70 | static struct nand_flash_dev nand_smartmedia_flash_ids[] = { |
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c index 508e9e04b092..396530d87ecf 100644 --- a/drivers/mtd/nand/tmio_nand.c +++ b/drivers/mtd/nand/tmio_nand.c | |||
@@ -357,7 +357,7 @@ static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio) | |||
357 | 357 | ||
358 | static int tmio_probe(struct platform_device *dev) | 358 | static int tmio_probe(struct platform_device *dev) |
359 | { | 359 | { |
360 | struct tmio_nand_data *data = dev->dev.platform_data; | 360 | struct tmio_nand_data *data = dev_get_platdata(&dev->dev); |
361 | struct resource *fcr = platform_get_resource(dev, | 361 | struct resource *fcr = platform_get_resource(dev, |
362 | IORESOURCE_MEM, 0); | 362 | IORESOURCE_MEM, 0); |
363 | struct resource *ccr = platform_get_resource(dev, | 363 | struct resource *ccr = platform_get_resource(dev, |
diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c index 7ed654c68b08..235714a421dd 100644 --- a/drivers/mtd/nand/txx9ndfmc.c +++ b/drivers/mtd/nand/txx9ndfmc.c | |||
@@ -87,7 +87,7 @@ static struct platform_device *mtd_to_platdev(struct mtd_info *mtd) | |||
87 | static void __iomem *ndregaddr(struct platform_device *dev, unsigned int reg) | 87 | static void __iomem *ndregaddr(struct platform_device *dev, unsigned int reg) |
88 | { | 88 | { |
89 | struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev); | 89 | struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev); |
90 | struct txx9ndfmc_platform_data *plat = dev->dev.platform_data; | 90 | struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev); |
91 | 91 | ||
92 | return drvdata->base + (reg << plat->shift); | 92 | return drvdata->base + (reg << plat->shift); |
93 | } | 93 | } |
@@ -138,7 +138,7 @@ static void txx9ndfmc_cmd_ctrl(struct mtd_info *mtd, int cmd, | |||
138 | struct nand_chip *chip = mtd->priv; | 138 | struct nand_chip *chip = mtd->priv; |
139 | struct txx9ndfmc_priv *txx9_priv = chip->priv; | 139 | struct txx9ndfmc_priv *txx9_priv = chip->priv; |
140 | struct platform_device *dev = txx9_priv->dev; | 140 | struct platform_device *dev = txx9_priv->dev; |
141 | struct txx9ndfmc_platform_data *plat = dev->dev.platform_data; | 141 | struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev); |
142 | 142 | ||
143 | if (ctrl & NAND_CTRL_CHANGE) { | 143 | if (ctrl & NAND_CTRL_CHANGE) { |
144 | u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR); | 144 | u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR); |
@@ -225,7 +225,7 @@ static void txx9ndfmc_enable_hwecc(struct mtd_info *mtd, int mode) | |||
225 | 225 | ||
226 | static void txx9ndfmc_initialize(struct platform_device *dev) | 226 | static void txx9ndfmc_initialize(struct platform_device *dev) |
227 | { | 227 | { |
228 | struct txx9ndfmc_platform_data *plat = dev->dev.platform_data; | 228 | struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev); |
229 | struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev); | 229 | struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev); |
230 | int tmout = 100; | 230 | int tmout = 100; |
231 | 231 | ||
@@ -274,19 +274,17 @@ static int txx9ndfmc_nand_scan(struct mtd_info *mtd) | |||
274 | 274 | ||
275 | static int __init txx9ndfmc_probe(struct platform_device *dev) | 275 | static int __init txx9ndfmc_probe(struct platform_device *dev) |
276 | { | 276 | { |
277 | struct txx9ndfmc_platform_data *plat = dev->dev.platform_data; | 277 | struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev); |
278 | int hold, spw; | 278 | int hold, spw; |
279 | int i; | 279 | int i; |
280 | struct txx9ndfmc_drvdata *drvdata; | 280 | struct txx9ndfmc_drvdata *drvdata; |
281 | unsigned long gbusclk = plat->gbus_clock; | 281 | unsigned long gbusclk = plat->gbus_clock; |
282 | struct resource *res; | 282 | struct resource *res; |
283 | 283 | ||
284 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
285 | if (!res) | ||
286 | return -ENODEV; | ||
287 | drvdata = devm_kzalloc(&dev->dev, sizeof(*drvdata), GFP_KERNEL); | 284 | drvdata = devm_kzalloc(&dev->dev, sizeof(*drvdata), GFP_KERNEL); |
288 | if (!drvdata) | 285 | if (!drvdata) |
289 | return -ENOMEM; | 286 | return -ENOMEM; |
287 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
290 | drvdata->base = devm_ioremap_resource(&dev->dev, res); | 288 | drvdata->base = devm_ioremap_resource(&dev->dev, res); |
291 | if (IS_ERR(drvdata->base)) | 289 | if (IS_ERR(drvdata->base)) |
292 | return PTR_ERR(drvdata->base); | 290 | return PTR_ERR(drvdata->base); |
@@ -387,7 +385,6 @@ static int __exit txx9ndfmc_remove(struct platform_device *dev) | |||
387 | struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev); | 385 | struct txx9ndfmc_drvdata *drvdata = platform_get_drvdata(dev); |
388 | int i; | 386 | int i; |
389 | 387 | ||
390 | platform_set_drvdata(dev, NULL); | ||
391 | if (!drvdata) | 388 | if (!drvdata) |
392 | return 0; | 389 | return 0; |
393 | for (i = 0; i < MAX_TXX9NDFMC_DEV; i++) { | 390 | for (i = 0; i < MAX_TXX9NDFMC_DEV; i++) { |
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index 553d6d6d5603..d64f8c30945f 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c | |||
@@ -20,6 +20,11 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/mtd/partitions.h> | 21 | #include <linux/mtd/partitions.h> |
22 | 22 | ||
23 | static bool node_has_compatible(struct device_node *pp) | ||
24 | { | ||
25 | return of_get_property(pp, "compatible", NULL); | ||
26 | } | ||
27 | |||
23 | static int parse_ofpart_partitions(struct mtd_info *master, | 28 | static int parse_ofpart_partitions(struct mtd_info *master, |
24 | struct mtd_partition **pparts, | 29 | struct mtd_partition **pparts, |
25 | struct mtd_part_parser_data *data) | 30 | struct mtd_part_parser_data *data) |
@@ -38,10 +43,13 @@ static int parse_ofpart_partitions(struct mtd_info *master, | |||
38 | return 0; | 43 | return 0; |
39 | 44 | ||
40 | /* First count the subnodes */ | 45 | /* First count the subnodes */ |
41 | pp = NULL; | ||
42 | nr_parts = 0; | 46 | nr_parts = 0; |
43 | while ((pp = of_get_next_child(node, pp))) | 47 | for_each_child_of_node(node, pp) { |
48 | if (node_has_compatible(pp)) | ||
49 | continue; | ||
50 | |||
44 | nr_parts++; | 51 | nr_parts++; |
52 | } | ||
45 | 53 | ||
46 | if (nr_parts == 0) | 54 | if (nr_parts == 0) |
47 | return 0; | 55 | return 0; |
@@ -50,13 +58,15 @@ static int parse_ofpart_partitions(struct mtd_info *master, | |||
50 | if (!*pparts) | 58 | if (!*pparts) |
51 | return -ENOMEM; | 59 | return -ENOMEM; |
52 | 60 | ||
53 | pp = NULL; | ||
54 | i = 0; | 61 | i = 0; |
55 | while ((pp = of_get_next_child(node, pp))) { | 62 | for_each_child_of_node(node, pp) { |
56 | const __be32 *reg; | 63 | const __be32 *reg; |
57 | int len; | 64 | int len; |
58 | int a_cells, s_cells; | 65 | int a_cells, s_cells; |
59 | 66 | ||
67 | if (node_has_compatible(pp)) | ||
68 | continue; | ||
69 | |||
60 | reg = of_get_property(pp, "reg", &len); | 70 | reg = of_get_property(pp, "reg", &len); |
61 | if (!reg) { | 71 | if (!reg) { |
62 | nr_parts--; | 72 | nr_parts--; |
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c index 9f11562f849d..63699fffc96d 100644 --- a/drivers/mtd/onenand/generic.c +++ b/drivers/mtd/onenand/generic.c | |||
@@ -38,7 +38,7 @@ struct onenand_info { | |||
38 | static int generic_onenand_probe(struct platform_device *pdev) | 38 | static int generic_onenand_probe(struct platform_device *pdev) |
39 | { | 39 | { |
40 | struct onenand_info *info; | 40 | struct onenand_info *info; |
41 | struct onenand_platform_data *pdata = pdev->dev.platform_data; | 41 | struct onenand_platform_data *pdata = dev_get_platdata(&pdev->dev); |
42 | struct resource *res = pdev->resource; | 42 | struct resource *res = pdev->resource; |
43 | unsigned long size = resource_size(res); | 43 | unsigned long size = resource_size(res); |
44 | int err; | 44 | int err; |
@@ -94,8 +94,6 @@ static int generic_onenand_remove(struct platform_device *pdev) | |||
94 | struct resource *res = pdev->resource; | 94 | struct resource *res = pdev->resource; |
95 | unsigned long size = resource_size(res); | 95 | unsigned long size = resource_size(res); |
96 | 96 | ||
97 | platform_set_drvdata(pdev, NULL); | ||
98 | |||
99 | if (info) { | 97 | if (info) { |
100 | onenand_release(&info->mtd); | 98 | onenand_release(&info->mtd); |
101 | release_mem_region(res->start, size); | 99 | release_mem_region(res->start, size); |
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index d98b198edd53..558071bf92de 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c | |||
@@ -639,7 +639,7 @@ static int omap2_onenand_probe(struct platform_device *pdev) | |||
639 | struct resource *res; | 639 | struct resource *res; |
640 | struct mtd_part_parser_data ppdata = {}; | 640 | struct mtd_part_parser_data ppdata = {}; |
641 | 641 | ||
642 | pdata = pdev->dev.platform_data; | 642 | pdata = dev_get_platdata(&pdev->dev); |
643 | if (pdata == NULL) { | 643 | if (pdata == NULL) { |
644 | dev_err(&pdev->dev, "platform data missing\n"); | 644 | dev_err(&pdev->dev, "platform data missing\n"); |
645 | return -ENODEV; | 645 | return -ENODEV; |
@@ -810,7 +810,6 @@ static int omap2_onenand_remove(struct platform_device *pdev) | |||
810 | if (c->dma_channel != -1) | 810 | if (c->dma_channel != -1) |
811 | omap_free_dma(c->dma_channel); | 811 | omap_free_dma(c->dma_channel); |
812 | omap2_onenand_shutdown(pdev); | 812 | omap2_onenand_shutdown(pdev); |
813 | platform_set_drvdata(pdev, NULL); | ||
814 | if (c->gpio_irq) { | 813 | if (c->gpio_irq) { |
815 | free_irq(gpio_to_irq(c->gpio_irq), c); | 814 | free_irq(gpio_to_irq(c->gpio_irq), c); |
816 | gpio_free(c->gpio_irq); | 815 | gpio_free(c->gpio_irq); |
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c index 66fe3b7e7851..08d0085f3e93 100644 --- a/drivers/mtd/onenand/onenand_bbt.c +++ b/drivers/mtd/onenand/onenand_bbt.c | |||
@@ -133,7 +133,6 @@ static inline int onenand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_desc | |||
133 | { | 133 | { |
134 | struct onenand_chip *this = mtd->priv; | 134 | struct onenand_chip *this = mtd->priv; |
135 | 135 | ||
136 | bd->options &= ~NAND_BBT_SCANEMPTY; | ||
137 | return create_bbt(mtd, this->page_buf, bd, -1); | 136 | return create_bbt(mtd, this->page_buf, bd, -1); |
138 | } | 137 | } |
139 | 138 | ||
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index 2cf74085f935..df7400dd4df8 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c | |||
@@ -867,7 +867,7 @@ static int s3c_onenand_probe(struct platform_device *pdev) | |||
867 | struct resource *r; | 867 | struct resource *r; |
868 | int size, err; | 868 | int size, err; |
869 | 869 | ||
870 | pdata = pdev->dev.platform_data; | 870 | pdata = dev_get_platdata(&pdev->dev); |
871 | /* No need to check pdata. the platform data is optional */ | 871 | /* No need to check pdata. the platform data is optional */ |
872 | 872 | ||
873 | size = sizeof(struct mtd_info) + sizeof(struct onenand_chip); | 873 | size = sizeof(struct mtd_info) + sizeof(struct onenand_chip); |
@@ -1073,7 +1073,6 @@ static int s3c_onenand_remove(struct platform_device *pdev) | |||
1073 | release_mem_region(onenand->base_res->start, | 1073 | release_mem_region(onenand->base_res->start, |
1074 | resource_size(onenand->base_res)); | 1074 | resource_size(onenand->base_res)); |
1075 | 1075 | ||
1076 | platform_set_drvdata(pdev, NULL); | ||
1077 | kfree(onenand->oob_buf); | 1076 | kfree(onenand->oob_buf); |
1078 | kfree(onenand->page_buf); | 1077 | kfree(onenand->page_buf); |
1079 | kfree(onenand); | 1078 | kfree(onenand); |
diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c index f9d5615c5727..4b8e89583f2a 100644 --- a/drivers/mtd/sm_ftl.c +++ b/drivers/mtd/sm_ftl.c | |||
@@ -22,7 +22,7 @@ | |||
22 | 22 | ||
23 | 23 | ||
24 | 24 | ||
25 | struct workqueue_struct *cache_flush_workqueue; | 25 | static struct workqueue_struct *cache_flush_workqueue; |
26 | 26 | ||
27 | static int cache_timeout = 1000; | 27 | static int cache_timeout = 1000; |
28 | module_param(cache_timeout, int, S_IRUGO); | 28 | module_param(cache_timeout, int, S_IRUGO); |
@@ -41,7 +41,7 @@ struct sm_sysfs_attribute { | |||
41 | int len; | 41 | int len; |
42 | }; | 42 | }; |
43 | 43 | ||
44 | ssize_t sm_attr_show(struct device *dev, struct device_attribute *attr, | 44 | static ssize_t sm_attr_show(struct device *dev, struct device_attribute *attr, |
45 | char *buf) | 45 | char *buf) |
46 | { | 46 | { |
47 | struct sm_sysfs_attribute *sm_attr = | 47 | struct sm_sysfs_attribute *sm_attr = |
@@ -54,7 +54,7 @@ ssize_t sm_attr_show(struct device *dev, struct device_attribute *attr, | |||
54 | 54 | ||
55 | #define NUM_ATTRIBUTES 1 | 55 | #define NUM_ATTRIBUTES 1 |
56 | #define SM_CIS_VENDOR_OFFSET 0x59 | 56 | #define SM_CIS_VENDOR_OFFSET 0x59 |
57 | struct attribute_group *sm_create_sysfs_attributes(struct sm_ftl *ftl) | 57 | static struct attribute_group *sm_create_sysfs_attributes(struct sm_ftl *ftl) |
58 | { | 58 | { |
59 | struct attribute_group *attr_group; | 59 | struct attribute_group *attr_group; |
60 | struct attribute **attributes; | 60 | struct attribute **attributes; |
@@ -107,7 +107,7 @@ error1: | |||
107 | return NULL; | 107 | return NULL; |
108 | } | 108 | } |
109 | 109 | ||
110 | void sm_delete_sysfs_attributes(struct sm_ftl *ftl) | 110 | static void sm_delete_sysfs_attributes(struct sm_ftl *ftl) |
111 | { | 111 | { |
112 | struct attribute **attributes = ftl->disk_attributes->attrs; | 112 | struct attribute **attributes = ftl->disk_attributes->attrs; |
113 | int i; | 113 | int i; |
@@ -571,7 +571,7 @@ static const uint8_t cis_signature[] = { | |||
571 | }; | 571 | }; |
572 | /* Find out media parameters. | 572 | /* Find out media parameters. |
573 | * This ideally has to be based on nand id, but for now device size is enough */ | 573 | * This ideally has to be based on nand id, but for now device size is enough */ |
574 | int sm_get_media_info(struct sm_ftl *ftl, struct mtd_info *mtd) | 574 | static int sm_get_media_info(struct sm_ftl *ftl, struct mtd_info *mtd) |
575 | { | 575 | { |
576 | int i; | 576 | int i; |
577 | int size_in_megs = mtd->size / (1024 * 1024); | 577 | int size_in_megs = mtd->size / (1024 * 1024); |
@@ -878,7 +878,7 @@ static int sm_init_zone(struct sm_ftl *ftl, int zone_num) | |||
878 | } | 878 | } |
879 | 879 | ||
880 | /* Get and automatically initialize an FTL mapping for one zone */ | 880 | /* Get and automatically initialize an FTL mapping for one zone */ |
881 | struct ftl_zone *sm_get_zone(struct sm_ftl *ftl, int zone_num) | 881 | static struct ftl_zone *sm_get_zone(struct sm_ftl *ftl, int zone_num) |
882 | { | 882 | { |
883 | struct ftl_zone *zone; | 883 | struct ftl_zone *zone; |
884 | int error; | 884 | int error; |
@@ -899,7 +899,7 @@ struct ftl_zone *sm_get_zone(struct sm_ftl *ftl, int zone_num) | |||
899 | /* ----------------- cache handling ------------------------------------------*/ | 899 | /* ----------------- cache handling ------------------------------------------*/ |
900 | 900 | ||
901 | /* Initialize the one block cache */ | 901 | /* Initialize the one block cache */ |
902 | void sm_cache_init(struct sm_ftl *ftl) | 902 | static void sm_cache_init(struct sm_ftl *ftl) |
903 | { | 903 | { |
904 | ftl->cache_data_invalid_bitmap = 0xFFFFFFFF; | 904 | ftl->cache_data_invalid_bitmap = 0xFFFFFFFF; |
905 | ftl->cache_clean = 1; | 905 | ftl->cache_clean = 1; |
@@ -909,7 +909,7 @@ void sm_cache_init(struct sm_ftl *ftl) | |||
909 | } | 909 | } |
910 | 910 | ||
911 | /* Put sector in one block cache */ | 911 | /* Put sector in one block cache */ |
912 | void sm_cache_put(struct sm_ftl *ftl, char *buffer, int boffset) | 912 | static void sm_cache_put(struct sm_ftl *ftl, char *buffer, int boffset) |
913 | { | 913 | { |
914 | memcpy(ftl->cache_data + boffset, buffer, SM_SECTOR_SIZE); | 914 | memcpy(ftl->cache_data + boffset, buffer, SM_SECTOR_SIZE); |
915 | clear_bit(boffset / SM_SECTOR_SIZE, &ftl->cache_data_invalid_bitmap); | 915 | clear_bit(boffset / SM_SECTOR_SIZE, &ftl->cache_data_invalid_bitmap); |
@@ -917,7 +917,7 @@ void sm_cache_put(struct sm_ftl *ftl, char *buffer, int boffset) | |||
917 | } | 917 | } |
918 | 918 | ||
919 | /* Read a sector from the cache */ | 919 | /* Read a sector from the cache */ |
920 | int sm_cache_get(struct sm_ftl *ftl, char *buffer, int boffset) | 920 | static int sm_cache_get(struct sm_ftl *ftl, char *buffer, int boffset) |
921 | { | 921 | { |
922 | if (test_bit(boffset / SM_SECTOR_SIZE, | 922 | if (test_bit(boffset / SM_SECTOR_SIZE, |
923 | &ftl->cache_data_invalid_bitmap)) | 923 | &ftl->cache_data_invalid_bitmap)) |
@@ -928,7 +928,7 @@ int sm_cache_get(struct sm_ftl *ftl, char *buffer, int boffset) | |||
928 | } | 928 | } |
929 | 929 | ||
930 | /* Write the cache to hardware */ | 930 | /* Write the cache to hardware */ |
931 | int sm_cache_flush(struct sm_ftl *ftl) | 931 | static int sm_cache_flush(struct sm_ftl *ftl) |
932 | { | 932 | { |
933 | struct ftl_zone *zone; | 933 | struct ftl_zone *zone; |
934 | 934 | ||
@@ -1274,10 +1274,10 @@ static struct mtd_blktrans_ops sm_ftl_ops = { | |||
1274 | static __init int sm_module_init(void) | 1274 | static __init int sm_module_init(void) |
1275 | { | 1275 | { |
1276 | int error = 0; | 1276 | int error = 0; |
1277 | cache_flush_workqueue = create_freezable_workqueue("smflush"); | ||
1278 | 1277 | ||
1279 | if (IS_ERR(cache_flush_workqueue)) | 1278 | cache_flush_workqueue = create_freezable_workqueue("smflush"); |
1280 | return PTR_ERR(cache_flush_workqueue); | 1279 | if (!cache_flush_workqueue) |
1280 | return -ENOMEM; | ||
1281 | 1281 | ||
1282 | error = register_mtd_blktrans(&sm_ftl_ops); | 1282 | error = register_mtd_blktrans(&sm_ftl_ops); |
1283 | if (error) | 1283 | if (error) |
diff --git a/drivers/mtd/tests/Makefile b/drivers/mtd/tests/Makefile index bd0065c0d359..937a829bb701 100644 --- a/drivers/mtd/tests/Makefile +++ b/drivers/mtd/tests/Makefile | |||
@@ -7,3 +7,12 @@ obj-$(CONFIG_MTD_TESTS) += mtd_subpagetest.o | |||
7 | obj-$(CONFIG_MTD_TESTS) += mtd_torturetest.o | 7 | obj-$(CONFIG_MTD_TESTS) += mtd_torturetest.o |
8 | obj-$(CONFIG_MTD_TESTS) += mtd_nandecctest.o | 8 | obj-$(CONFIG_MTD_TESTS) += mtd_nandecctest.o |
9 | obj-$(CONFIG_MTD_TESTS) += mtd_nandbiterrs.o | 9 | obj-$(CONFIG_MTD_TESTS) += mtd_nandbiterrs.o |
10 | |||
11 | mtd_oobtest-objs := oobtest.o mtd_test.o | ||
12 | mtd_pagetest-objs := pagetest.o mtd_test.o | ||
13 | mtd_readtest-objs := readtest.o mtd_test.o | ||
14 | mtd_speedtest-objs := speedtest.o mtd_test.o | ||
15 | mtd_stresstest-objs := stresstest.o mtd_test.o | ||
16 | mtd_subpagetest-objs := subpagetest.o mtd_test.o | ||
17 | mtd_torturetest-objs := torturetest.o mtd_test.o | ||
18 | mtd_nandbiterrs-objs := nandbiterrs.o mtd_test.o | ||
diff --git a/drivers/mtd/tests/mtd_test.c b/drivers/mtd/tests/mtd_test.c new file mode 100644 index 000000000000..c818a63532e7 --- /dev/null +++ b/drivers/mtd/tests/mtd_test.c | |||
@@ -0,0 +1,114 @@ | |||
1 | #define pr_fmt(fmt) "mtd_test: " fmt | ||
2 | |||
3 | #include <linux/init.h> | ||
4 | #include <linux/module.h> | ||
5 | #include <linux/sched.h> | ||
6 | #include <linux/printk.h> | ||
7 | |||
8 | #include "mtd_test.h" | ||
9 | |||
10 | int mtdtest_erase_eraseblock(struct mtd_info *mtd, unsigned int ebnum) | ||
11 | { | ||
12 | int err; | ||
13 | struct erase_info ei; | ||
14 | loff_t addr = ebnum * mtd->erasesize; | ||
15 | |||
16 | memset(&ei, 0, sizeof(struct erase_info)); | ||
17 | ei.mtd = mtd; | ||
18 | ei.addr = addr; | ||
19 | ei.len = mtd->erasesize; | ||
20 | |||
21 | err = mtd_erase(mtd, &ei); | ||
22 | if (err) { | ||
23 | pr_info("error %d while erasing EB %d\n", err, ebnum); | ||
24 | return err; | ||
25 | } | ||
26 | |||
27 | if (ei.state == MTD_ERASE_FAILED) { | ||
28 | pr_info("some erase error occurred at EB %d\n", ebnum); | ||
29 | return -EIO; | ||
30 | } | ||
31 | return 0; | ||
32 | } | ||
33 | |||
34 | static int is_block_bad(struct mtd_info *mtd, unsigned int ebnum) | ||
35 | { | ||
36 | int ret; | ||
37 | loff_t addr = ebnum * mtd->erasesize; | ||
38 | |||
39 | ret = mtd_block_isbad(mtd, addr); | ||
40 | if (ret) | ||
41 | pr_info("block %d is bad\n", ebnum); | ||
42 | |||
43 | return ret; | ||
44 | } | ||
45 | |||
46 | int mtdtest_scan_for_bad_eraseblocks(struct mtd_info *mtd, unsigned char *bbt, | ||
47 | unsigned int eb, int ebcnt) | ||
48 | { | ||
49 | int i, bad = 0; | ||
50 | |||
51 | if (!mtd_can_have_bb(mtd)) | ||
52 | return 0; | ||
53 | |||
54 | pr_info("scanning for bad eraseblocks\n"); | ||
55 | for (i = 0; i < ebcnt; ++i) { | ||
56 | bbt[i] = is_block_bad(mtd, eb + i) ? 1 : 0; | ||
57 | if (bbt[i]) | ||
58 | bad += 1; | ||
59 | cond_resched(); | ||
60 | } | ||
61 | pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | int mtdtest_erase_good_eraseblocks(struct mtd_info *mtd, unsigned char *bbt, | ||
67 | unsigned int eb, int ebcnt) | ||
68 | { | ||
69 | int err; | ||
70 | unsigned int i; | ||
71 | |||
72 | for (i = 0; i < ebcnt; ++i) { | ||
73 | if (bbt[i]) | ||
74 | continue; | ||
75 | err = mtdtest_erase_eraseblock(mtd, eb + i); | ||
76 | if (err) | ||
77 | return err; | ||
78 | cond_resched(); | ||
79 | } | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | int mtdtest_read(struct mtd_info *mtd, loff_t addr, size_t size, void *buf) | ||
85 | { | ||
86 | size_t read; | ||
87 | int err; | ||
88 | |||
89 | err = mtd_read(mtd, addr, size, &read, buf); | ||
90 | /* Ignore corrected ECC errors */ | ||
91 | if (mtd_is_bitflip(err)) | ||
92 | err = 0; | ||
93 | if (!err && read != size) | ||
94 | err = -EIO; | ||
95 | if (err) | ||
96 | pr_err("error: read failed at %#llx\n", addr); | ||
97 | |||
98 | return err; | ||
99 | } | ||
100 | |||
101 | int mtdtest_write(struct mtd_info *mtd, loff_t addr, size_t size, | ||
102 | const void *buf) | ||
103 | { | ||
104 | size_t written; | ||
105 | int err; | ||
106 | |||
107 | err = mtd_write(mtd, addr, size, &written, buf); | ||
108 | if (!err && written != size) | ||
109 | err = -EIO; | ||
110 | if (err) | ||
111 | pr_err("error: write failed at %#llx\n", addr); | ||
112 | |||
113 | return err; | ||
114 | } | ||
diff --git a/drivers/mtd/tests/mtd_test.h b/drivers/mtd/tests/mtd_test.h new file mode 100644 index 000000000000..f437c776c54f --- /dev/null +++ b/drivers/mtd/tests/mtd_test.h | |||
@@ -0,0 +1,11 @@ | |||
1 | #include <linux/mtd/mtd.h> | ||
2 | |||
3 | int mtdtest_erase_eraseblock(struct mtd_info *mtd, unsigned int ebnum); | ||
4 | int mtdtest_scan_for_bad_eraseblocks(struct mtd_info *mtd, unsigned char *bbt, | ||
5 | unsigned int eb, int ebcnt); | ||
6 | int mtdtest_erase_good_eraseblocks(struct mtd_info *mtd, unsigned char *bbt, | ||
7 | unsigned int eb, int ebcnt); | ||
8 | |||
9 | int mtdtest_read(struct mtd_info *mtd, loff_t addr, size_t size, void *buf); | ||
10 | int mtdtest_write(struct mtd_info *mtd, loff_t addr, size_t size, | ||
11 | const void *buf); | ||
diff --git a/drivers/mtd/tests/mtd_nandbiterrs.c b/drivers/mtd/tests/nandbiterrs.c index 207bf9a9972f..3cd3aabbe1cd 100644 --- a/drivers/mtd/tests/mtd_nandbiterrs.c +++ b/drivers/mtd/tests/nandbiterrs.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <linux/err.h> | 49 | #include <linux/err.h> |
50 | #include <linux/mtd/nand.h> | 50 | #include <linux/mtd/nand.h> |
51 | #include <linux/slab.h> | 51 | #include <linux/slab.h> |
52 | #include "mtd_test.h" | ||
52 | 53 | ||
53 | static int dev; | 54 | static int dev; |
54 | module_param(dev, int, S_IRUGO); | 55 | module_param(dev, int, S_IRUGO); |
@@ -98,47 +99,13 @@ static uint8_t hash(unsigned offset) | |||
98 | return c; | 99 | return c; |
99 | } | 100 | } |
100 | 101 | ||
101 | static int erase_block(void) | ||
102 | { | ||
103 | int err; | ||
104 | struct erase_info ei; | ||
105 | loff_t addr = eraseblock * mtd->erasesize; | ||
106 | |||
107 | pr_info("erase_block\n"); | ||
108 | |||
109 | memset(&ei, 0, sizeof(struct erase_info)); | ||
110 | ei.mtd = mtd; | ||
111 | ei.addr = addr; | ||
112 | ei.len = mtd->erasesize; | ||
113 | |||
114 | err = mtd_erase(mtd, &ei); | ||
115 | if (err || ei.state == MTD_ERASE_FAILED) { | ||
116 | pr_err("error %d while erasing\n", err); | ||
117 | if (!err) | ||
118 | err = -EIO; | ||
119 | return err; | ||
120 | } | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | /* Writes wbuffer to page */ | 102 | /* Writes wbuffer to page */ |
126 | static int write_page(int log) | 103 | static int write_page(int log) |
127 | { | 104 | { |
128 | int err = 0; | ||
129 | size_t written; | ||
130 | |||
131 | if (log) | 105 | if (log) |
132 | pr_info("write_page\n"); | 106 | pr_info("write_page\n"); |
133 | 107 | ||
134 | err = mtd_write(mtd, offset, mtd->writesize, &written, wbuffer); | 108 | return mtdtest_write(mtd, offset, mtd->writesize, wbuffer); |
135 | if (err || written != mtd->writesize) { | ||
136 | pr_err("error: write failed at %#llx\n", (long long)offset); | ||
137 | if (!err) | ||
138 | err = -EIO; | ||
139 | } | ||
140 | |||
141 | return err; | ||
142 | } | 109 | } |
143 | 110 | ||
144 | /* Re-writes the data area while leaving the OOB alone. */ | 111 | /* Re-writes the data area while leaving the OOB alone. */ |
@@ -415,7 +382,7 @@ static int __init mtd_nandbiterrs_init(void) | |||
415 | goto exit_rbuffer; | 382 | goto exit_rbuffer; |
416 | } | 383 | } |
417 | 384 | ||
418 | err = erase_block(); | 385 | err = mtdtest_erase_eraseblock(mtd, eraseblock); |
419 | if (err) | 386 | if (err) |
420 | goto exit_error; | 387 | goto exit_error; |
421 | 388 | ||
@@ -428,7 +395,7 @@ static int __init mtd_nandbiterrs_init(void) | |||
428 | goto exit_error; | 395 | goto exit_error; |
429 | 396 | ||
430 | /* We leave the block un-erased in case of test failure. */ | 397 | /* We leave the block un-erased in case of test failure. */ |
431 | err = erase_block(); | 398 | err = mtdtest_erase_eraseblock(mtd, eraseblock); |
432 | if (err) | 399 | if (err) |
433 | goto exit_error; | 400 | goto exit_error; |
434 | 401 | ||
diff --git a/drivers/mtd/tests/mtd_oobtest.c b/drivers/mtd/tests/oobtest.c index 3e24b379ffa4..ff35c465bfee 100644 --- a/drivers/mtd/tests/mtd_oobtest.c +++ b/drivers/mtd/tests/oobtest.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
32 | #include <linux/random.h> | 32 | #include <linux/random.h> |
33 | 33 | ||
34 | #include "mtd_test.h" | ||
35 | |||
34 | static int dev = -EINVAL; | 36 | static int dev = -EINVAL; |
35 | module_param(dev, int, S_IRUGO); | 37 | module_param(dev, int, S_IRUGO); |
36 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 38 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
@@ -49,49 +51,6 @@ static int use_len_max; | |||
49 | static int vary_offset; | 51 | static int vary_offset; |
50 | static struct rnd_state rnd_state; | 52 | static struct rnd_state rnd_state; |
51 | 53 | ||
52 | static int erase_eraseblock(int ebnum) | ||
53 | { | ||
54 | int err; | ||
55 | struct erase_info ei; | ||
56 | loff_t addr = ebnum * mtd->erasesize; | ||
57 | |||
58 | memset(&ei, 0, sizeof(struct erase_info)); | ||
59 | ei.mtd = mtd; | ||
60 | ei.addr = addr; | ||
61 | ei.len = mtd->erasesize; | ||
62 | |||
63 | err = mtd_erase(mtd, &ei); | ||
64 | if (err) { | ||
65 | pr_err("error %d while erasing EB %d\n", err, ebnum); | ||
66 | return err; | ||
67 | } | ||
68 | |||
69 | if (ei.state == MTD_ERASE_FAILED) { | ||
70 | pr_err("some erase error occurred at EB %d\n", ebnum); | ||
71 | return -EIO; | ||
72 | } | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static int erase_whole_device(void) | ||
78 | { | ||
79 | int err; | ||
80 | unsigned int i; | ||
81 | |||
82 | pr_info("erasing whole device\n"); | ||
83 | for (i = 0; i < ebcnt; ++i) { | ||
84 | if (bbt[i]) | ||
85 | continue; | ||
86 | err = erase_eraseblock(i); | ||
87 | if (err) | ||
88 | return err; | ||
89 | cond_resched(); | ||
90 | } | ||
91 | pr_info("erased %u eraseblocks\n", i); | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static void do_vary_offset(void) | 54 | static void do_vary_offset(void) |
96 | { | 55 | { |
97 | use_len -= 1; | 56 | use_len -= 1; |
@@ -304,38 +263,6 @@ static int verify_all_eraseblocks(void) | |||
304 | return 0; | 263 | return 0; |
305 | } | 264 | } |
306 | 265 | ||
307 | static int is_block_bad(int ebnum) | ||
308 | { | ||
309 | int ret; | ||
310 | loff_t addr = ebnum * mtd->erasesize; | ||
311 | |||
312 | ret = mtd_block_isbad(mtd, addr); | ||
313 | if (ret) | ||
314 | pr_info("block %d is bad\n", ebnum); | ||
315 | return ret; | ||
316 | } | ||
317 | |||
318 | static int scan_for_bad_eraseblocks(void) | ||
319 | { | ||
320 | int i, bad = 0; | ||
321 | |||
322 | bbt = kmalloc(ebcnt, GFP_KERNEL); | ||
323 | if (!bbt) { | ||
324 | pr_err("error: cannot allocate memory\n"); | ||
325 | return -ENOMEM; | ||
326 | } | ||
327 | |||
328 | pr_info("scanning for bad eraseblocks\n"); | ||
329 | for (i = 0; i < ebcnt; ++i) { | ||
330 | bbt[i] = is_block_bad(i) ? 1 : 0; | ||
331 | if (bbt[i]) | ||
332 | bad += 1; | ||
333 | cond_resched(); | ||
334 | } | ||
335 | pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); | ||
336 | return 0; | ||
337 | } | ||
338 | |||
339 | static int __init mtd_oobtest_init(void) | 266 | static int __init mtd_oobtest_init(void) |
340 | { | 267 | { |
341 | int err = 0; | 268 | int err = 0; |
@@ -380,17 +307,16 @@ static int __init mtd_oobtest_init(void) | |||
380 | 307 | ||
381 | err = -ENOMEM; | 308 | err = -ENOMEM; |
382 | readbuf = kmalloc(mtd->erasesize, GFP_KERNEL); | 309 | readbuf = kmalloc(mtd->erasesize, GFP_KERNEL); |
383 | if (!readbuf) { | 310 | if (!readbuf) |
384 | pr_err("error: cannot allocate memory\n"); | ||
385 | goto out; | 311 | goto out; |
386 | } | ||
387 | writebuf = kmalloc(mtd->erasesize, GFP_KERNEL); | 312 | writebuf = kmalloc(mtd->erasesize, GFP_KERNEL); |
388 | if (!writebuf) { | 313 | if (!writebuf) |
389 | pr_err("error: cannot allocate memory\n"); | 314 | goto out; |
315 | bbt = kzalloc(ebcnt, GFP_KERNEL); | ||
316 | if (!bbt) | ||
390 | goto out; | 317 | goto out; |
391 | } | ||
392 | 318 | ||
393 | err = scan_for_bad_eraseblocks(); | 319 | err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt); |
394 | if (err) | 320 | if (err) |
395 | goto out; | 321 | goto out; |
396 | 322 | ||
@@ -402,7 +328,7 @@ static int __init mtd_oobtest_init(void) | |||
402 | /* First test: write all OOB, read it back and verify */ | 328 | /* First test: write all OOB, read it back and verify */ |
403 | pr_info("test 1 of 5\n"); | 329 | pr_info("test 1 of 5\n"); |
404 | 330 | ||
405 | err = erase_whole_device(); | 331 | err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); |
406 | if (err) | 332 | if (err) |
407 | goto out; | 333 | goto out; |
408 | 334 | ||
@@ -422,7 +348,7 @@ static int __init mtd_oobtest_init(void) | |||
422 | */ | 348 | */ |
423 | pr_info("test 2 of 5\n"); | 349 | pr_info("test 2 of 5\n"); |
424 | 350 | ||
425 | err = erase_whole_device(); | 351 | err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); |
426 | if (err) | 352 | if (err) |
427 | goto out; | 353 | goto out; |
428 | 354 | ||
@@ -452,7 +378,7 @@ static int __init mtd_oobtest_init(void) | |||
452 | */ | 378 | */ |
453 | pr_info("test 3 of 5\n"); | 379 | pr_info("test 3 of 5\n"); |
454 | 380 | ||
455 | err = erase_whole_device(); | 381 | err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); |
456 | if (err) | 382 | if (err) |
457 | goto out; | 383 | goto out; |
458 | 384 | ||
@@ -485,7 +411,7 @@ static int __init mtd_oobtest_init(void) | |||
485 | /* Fourth test: try to write off end of device */ | 411 | /* Fourth test: try to write off end of device */ |
486 | pr_info("test 4 of 5\n"); | 412 | pr_info("test 4 of 5\n"); |
487 | 413 | ||
488 | err = erase_whole_device(); | 414 | err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); |
489 | if (err) | 415 | if (err) |
490 | goto out; | 416 | goto out; |
491 | 417 | ||
@@ -577,7 +503,7 @@ static int __init mtd_oobtest_init(void) | |||
577 | errcnt += 1; | 503 | errcnt += 1; |
578 | } | 504 | } |
579 | 505 | ||
580 | err = erase_eraseblock(ebcnt - 1); | 506 | err = mtdtest_erase_eraseblock(mtd, ebcnt - 1); |
581 | if (err) | 507 | if (err) |
582 | goto out; | 508 | goto out; |
583 | 509 | ||
@@ -626,7 +552,7 @@ static int __init mtd_oobtest_init(void) | |||
626 | pr_info("test 5 of 5\n"); | 552 | pr_info("test 5 of 5\n"); |
627 | 553 | ||
628 | /* Erase all eraseblocks */ | 554 | /* Erase all eraseblocks */ |
629 | err = erase_whole_device(); | 555 | err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); |
630 | if (err) | 556 | if (err) |
631 | goto out; | 557 | goto out; |
632 | 558 | ||
diff --git a/drivers/mtd/tests/mtd_pagetest.c b/drivers/mtd/tests/pagetest.c index 0c1140b6c286..44b96e999ad4 100644 --- a/drivers/mtd/tests/mtd_pagetest.c +++ b/drivers/mtd/tests/pagetest.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
32 | #include <linux/random.h> | 32 | #include <linux/random.h> |
33 | 33 | ||
34 | #include "mtd_test.h" | ||
35 | |||
34 | static int dev = -EINVAL; | 36 | static int dev = -EINVAL; |
35 | module_param(dev, int, S_IRUGO); | 37 | module_param(dev, int, S_IRUGO); |
36 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 38 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
@@ -48,52 +50,18 @@ static int pgcnt; | |||
48 | static int errcnt; | 50 | static int errcnt; |
49 | static struct rnd_state rnd_state; | 51 | static struct rnd_state rnd_state; |
50 | 52 | ||
51 | static int erase_eraseblock(int ebnum) | ||
52 | { | ||
53 | int err; | ||
54 | struct erase_info ei; | ||
55 | loff_t addr = ebnum * mtd->erasesize; | ||
56 | |||
57 | memset(&ei, 0, sizeof(struct erase_info)); | ||
58 | ei.mtd = mtd; | ||
59 | ei.addr = addr; | ||
60 | ei.len = mtd->erasesize; | ||
61 | |||
62 | err = mtd_erase(mtd, &ei); | ||
63 | if (err) { | ||
64 | pr_err("error %d while erasing EB %d\n", err, ebnum); | ||
65 | return err; | ||
66 | } | ||
67 | |||
68 | if (ei.state == MTD_ERASE_FAILED) { | ||
69 | pr_err("some erase error occurred at EB %d\n", | ||
70 | ebnum); | ||
71 | return -EIO; | ||
72 | } | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static int write_eraseblock(int ebnum) | 53 | static int write_eraseblock(int ebnum) |
78 | { | 54 | { |
79 | int err = 0; | ||
80 | size_t written; | ||
81 | loff_t addr = ebnum * mtd->erasesize; | 55 | loff_t addr = ebnum * mtd->erasesize; |
82 | 56 | ||
83 | prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize); | 57 | prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize); |
84 | cond_resched(); | 58 | cond_resched(); |
85 | err = mtd_write(mtd, addr, mtd->erasesize, &written, writebuf); | 59 | return mtdtest_write(mtd, addr, mtd->erasesize, writebuf); |
86 | if (err || written != mtd->erasesize) | ||
87 | pr_err("error: write failed at %#llx\n", | ||
88 | (long long)addr); | ||
89 | |||
90 | return err; | ||
91 | } | 60 | } |
92 | 61 | ||
93 | static int verify_eraseblock(int ebnum) | 62 | static int verify_eraseblock(int ebnum) |
94 | { | 63 | { |
95 | uint32_t j; | 64 | uint32_t j; |
96 | size_t read; | ||
97 | int err = 0, i; | 65 | int err = 0, i; |
98 | loff_t addr0, addrn; | 66 | loff_t addr0, addrn; |
99 | loff_t addr = ebnum * mtd->erasesize; | 67 | loff_t addr = ebnum * mtd->erasesize; |
@@ -109,31 +77,16 @@ static int verify_eraseblock(int ebnum) | |||
109 | prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize); | 77 | prandom_bytes_state(&rnd_state, writebuf, mtd->erasesize); |
110 | for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) { | 78 | for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) { |
111 | /* Do a read to set the internal dataRAMs to different data */ | 79 | /* Do a read to set the internal dataRAMs to different data */ |
112 | err = mtd_read(mtd, addr0, bufsize, &read, twopages); | 80 | err = mtdtest_read(mtd, addr0, bufsize, twopages); |
113 | if (mtd_is_bitflip(err)) | 81 | if (err) |
114 | err = 0; | ||
115 | if (err || read != bufsize) { | ||
116 | pr_err("error: read failed at %#llx\n", | ||
117 | (long long)addr0); | ||
118 | return err; | 82 | return err; |
119 | } | 83 | err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages); |
120 | err = mtd_read(mtd, addrn - bufsize, bufsize, &read, twopages); | 84 | if (err) |
121 | if (mtd_is_bitflip(err)) | ||
122 | err = 0; | ||
123 | if (err || read != bufsize) { | ||
124 | pr_err("error: read failed at %#llx\n", | ||
125 | (long long)(addrn - bufsize)); | ||
126 | return err; | 85 | return err; |
127 | } | ||
128 | memset(twopages, 0, bufsize); | 86 | memset(twopages, 0, bufsize); |
129 | err = mtd_read(mtd, addr, bufsize, &read, twopages); | 87 | err = mtdtest_read(mtd, addr, bufsize, twopages); |
130 | if (mtd_is_bitflip(err)) | 88 | if (err) |
131 | err = 0; | ||
132 | if (err || read != bufsize) { | ||
133 | pr_err("error: read failed at %#llx\n", | ||
134 | (long long)addr); | ||
135 | break; | 89 | break; |
136 | } | ||
137 | if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) { | 90 | if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) { |
138 | pr_err("error: verify failed at %#llx\n", | 91 | pr_err("error: verify failed at %#llx\n", |
139 | (long long)addr); | 92 | (long long)addr); |
@@ -145,31 +98,16 @@ static int verify_eraseblock(int ebnum) | |||
145 | struct rnd_state old_state = rnd_state; | 98 | struct rnd_state old_state = rnd_state; |
146 | 99 | ||
147 | /* Do a read to set the internal dataRAMs to different data */ | 100 | /* Do a read to set the internal dataRAMs to different data */ |
148 | err = mtd_read(mtd, addr0, bufsize, &read, twopages); | 101 | err = mtdtest_read(mtd, addr0, bufsize, twopages); |
149 | if (mtd_is_bitflip(err)) | 102 | if (err) |
150 | err = 0; | ||
151 | if (err || read != bufsize) { | ||
152 | pr_err("error: read failed at %#llx\n", | ||
153 | (long long)addr0); | ||
154 | return err; | 103 | return err; |
155 | } | 104 | err = mtdtest_read(mtd, addrn - bufsize, bufsize, twopages); |
156 | err = mtd_read(mtd, addrn - bufsize, bufsize, &read, twopages); | 105 | if (err) |
157 | if (mtd_is_bitflip(err)) | ||
158 | err = 0; | ||
159 | if (err || read != bufsize) { | ||
160 | pr_err("error: read failed at %#llx\n", | ||
161 | (long long)(addrn - bufsize)); | ||
162 | return err; | 106 | return err; |
163 | } | ||
164 | memset(twopages, 0, bufsize); | 107 | memset(twopages, 0, bufsize); |
165 | err = mtd_read(mtd, addr, bufsize, &read, twopages); | 108 | err = mtdtest_read(mtd, addr, bufsize, twopages); |
166 | if (mtd_is_bitflip(err)) | 109 | if (err) |
167 | err = 0; | ||
168 | if (err || read != bufsize) { | ||
169 | pr_err("error: read failed at %#llx\n", | ||
170 | (long long)addr); | ||
171 | return err; | 110 | return err; |
172 | } | ||
173 | memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize); | 111 | memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize); |
174 | prandom_bytes_state(&rnd_state, boundary + pgsize, pgsize); | 112 | prandom_bytes_state(&rnd_state, boundary + pgsize, pgsize); |
175 | if (memcmp(twopages, boundary, bufsize)) { | 113 | if (memcmp(twopages, boundary, bufsize)) { |
@@ -184,17 +122,14 @@ static int verify_eraseblock(int ebnum) | |||
184 | 122 | ||
185 | static int crosstest(void) | 123 | static int crosstest(void) |
186 | { | 124 | { |
187 | size_t read; | ||
188 | int err = 0, i; | 125 | int err = 0, i; |
189 | loff_t addr, addr0, addrn; | 126 | loff_t addr, addr0, addrn; |
190 | unsigned char *pp1, *pp2, *pp3, *pp4; | 127 | unsigned char *pp1, *pp2, *pp3, *pp4; |
191 | 128 | ||
192 | pr_info("crosstest\n"); | 129 | pr_info("crosstest\n"); |
193 | pp1 = kmalloc(pgsize * 4, GFP_KERNEL); | 130 | pp1 = kmalloc(pgsize * 4, GFP_KERNEL); |
194 | if (!pp1) { | 131 | if (!pp1) |
195 | pr_err("error: cannot allocate memory\n"); | ||
196 | return -ENOMEM; | 132 | return -ENOMEM; |
197 | } | ||
198 | pp2 = pp1 + pgsize; | 133 | pp2 = pp1 + pgsize; |
199 | pp3 = pp2 + pgsize; | 134 | pp3 = pp2 + pgsize; |
200 | pp4 = pp3 + pgsize; | 135 | pp4 = pp3 + pgsize; |
@@ -210,24 +145,16 @@ static int crosstest(void) | |||
210 | 145 | ||
211 | /* Read 2nd-to-last page to pp1 */ | 146 | /* Read 2nd-to-last page to pp1 */ |
212 | addr = addrn - pgsize - pgsize; | 147 | addr = addrn - pgsize - pgsize; |
213 | err = mtd_read(mtd, addr, pgsize, &read, pp1); | 148 | err = mtdtest_read(mtd, addr, pgsize, pp1); |
214 | if (mtd_is_bitflip(err)) | 149 | if (err) { |
215 | err = 0; | ||
216 | if (err || read != pgsize) { | ||
217 | pr_err("error: read failed at %#llx\n", | ||
218 | (long long)addr); | ||
219 | kfree(pp1); | 150 | kfree(pp1); |
220 | return err; | 151 | return err; |
221 | } | 152 | } |
222 | 153 | ||
223 | /* Read 3rd-to-last page to pp1 */ | 154 | /* Read 3rd-to-last page to pp1 */ |
224 | addr = addrn - pgsize - pgsize - pgsize; | 155 | addr = addrn - pgsize - pgsize - pgsize; |
225 | err = mtd_read(mtd, addr, pgsize, &read, pp1); | 156 | err = mtdtest_read(mtd, addr, pgsize, pp1); |
226 | if (mtd_is_bitflip(err)) | 157 | if (err) { |
227 | err = 0; | ||
228 | if (err || read != pgsize) { | ||
229 | pr_err("error: read failed at %#llx\n", | ||
230 | (long long)addr); | ||
231 | kfree(pp1); | 158 | kfree(pp1); |
232 | return err; | 159 | return err; |
233 | } | 160 | } |
@@ -235,12 +162,8 @@ static int crosstest(void) | |||
235 | /* Read first page to pp2 */ | 162 | /* Read first page to pp2 */ |
236 | addr = addr0; | 163 | addr = addr0; |
237 | pr_info("reading page at %#llx\n", (long long)addr); | 164 | pr_info("reading page at %#llx\n", (long long)addr); |
238 | err = mtd_read(mtd, addr, pgsize, &read, pp2); | 165 | err = mtdtest_read(mtd, addr, pgsize, pp2); |
239 | if (mtd_is_bitflip(err)) | 166 | if (err) { |
240 | err = 0; | ||
241 | if (err || read != pgsize) { | ||
242 | pr_err("error: read failed at %#llx\n", | ||
243 | (long long)addr); | ||
244 | kfree(pp1); | 167 | kfree(pp1); |
245 | return err; | 168 | return err; |
246 | } | 169 | } |
@@ -248,12 +171,8 @@ static int crosstest(void) | |||
248 | /* Read last page to pp3 */ | 171 | /* Read last page to pp3 */ |
249 | addr = addrn - pgsize; | 172 | addr = addrn - pgsize; |
250 | pr_info("reading page at %#llx\n", (long long)addr); | 173 | pr_info("reading page at %#llx\n", (long long)addr); |
251 | err = mtd_read(mtd, addr, pgsize, &read, pp3); | 174 | err = mtdtest_read(mtd, addr, pgsize, pp3); |
252 | if (mtd_is_bitflip(err)) | 175 | if (err) { |
253 | err = 0; | ||
254 | if (err || read != pgsize) { | ||
255 | pr_err("error: read failed at %#llx\n", | ||
256 | (long long)addr); | ||
257 | kfree(pp1); | 176 | kfree(pp1); |
258 | return err; | 177 | return err; |
259 | } | 178 | } |
@@ -261,12 +180,8 @@ static int crosstest(void) | |||
261 | /* Read first page again to pp4 */ | 180 | /* Read first page again to pp4 */ |
262 | addr = addr0; | 181 | addr = addr0; |
263 | pr_info("reading page at %#llx\n", (long long)addr); | 182 | pr_info("reading page at %#llx\n", (long long)addr); |
264 | err = mtd_read(mtd, addr, pgsize, &read, pp4); | 183 | err = mtdtest_read(mtd, addr, pgsize, pp4); |
265 | if (mtd_is_bitflip(err)) | 184 | if (err) { |
266 | err = 0; | ||
267 | if (err || read != pgsize) { | ||
268 | pr_err("error: read failed at %#llx\n", | ||
269 | (long long)addr); | ||
270 | kfree(pp1); | 185 | kfree(pp1); |
271 | return err; | 186 | return err; |
272 | } | 187 | } |
@@ -285,7 +200,6 @@ static int crosstest(void) | |||
285 | 200 | ||
286 | static int erasecrosstest(void) | 201 | static int erasecrosstest(void) |
287 | { | 202 | { |
288 | size_t read, written; | ||
289 | int err = 0, i, ebnum, ebnum2; | 203 | int err = 0, i, ebnum, ebnum2; |
290 | loff_t addr0; | 204 | loff_t addr0; |
291 | char *readbuf = twopages; | 205 | char *readbuf = twopages; |
@@ -304,30 +218,22 @@ static int erasecrosstest(void) | |||
304 | ebnum2 -= 1; | 218 | ebnum2 -= 1; |
305 | 219 | ||
306 | pr_info("erasing block %d\n", ebnum); | 220 | pr_info("erasing block %d\n", ebnum); |
307 | err = erase_eraseblock(ebnum); | 221 | err = mtdtest_erase_eraseblock(mtd, ebnum); |
308 | if (err) | 222 | if (err) |
309 | return err; | 223 | return err; |
310 | 224 | ||
311 | pr_info("writing 1st page of block %d\n", ebnum); | 225 | pr_info("writing 1st page of block %d\n", ebnum); |
312 | prandom_bytes_state(&rnd_state, writebuf, pgsize); | 226 | prandom_bytes_state(&rnd_state, writebuf, pgsize); |
313 | strcpy(writebuf, "There is no data like this!"); | 227 | strcpy(writebuf, "There is no data like this!"); |
314 | err = mtd_write(mtd, addr0, pgsize, &written, writebuf); | 228 | err = mtdtest_write(mtd, addr0, pgsize, writebuf); |
315 | if (err || written != pgsize) { | 229 | if (err) |
316 | pr_info("error: write failed at %#llx\n", | 230 | return err; |
317 | (long long)addr0); | ||
318 | return err ? err : -1; | ||
319 | } | ||
320 | 231 | ||
321 | pr_info("reading 1st page of block %d\n", ebnum); | 232 | pr_info("reading 1st page of block %d\n", ebnum); |
322 | memset(readbuf, 0, pgsize); | 233 | memset(readbuf, 0, pgsize); |
323 | err = mtd_read(mtd, addr0, pgsize, &read, readbuf); | 234 | err = mtdtest_read(mtd, addr0, pgsize, readbuf); |
324 | if (mtd_is_bitflip(err)) | 235 | if (err) |
325 | err = 0; | 236 | return err; |
326 | if (err || read != pgsize) { | ||
327 | pr_err("error: read failed at %#llx\n", | ||
328 | (long long)addr0); | ||
329 | return err ? err : -1; | ||
330 | } | ||
331 | 237 | ||
332 | pr_info("verifying 1st page of block %d\n", ebnum); | 238 | pr_info("verifying 1st page of block %d\n", ebnum); |
333 | if (memcmp(writebuf, readbuf, pgsize)) { | 239 | if (memcmp(writebuf, readbuf, pgsize)) { |
@@ -337,35 +243,27 @@ static int erasecrosstest(void) | |||
337 | } | 243 | } |
338 | 244 | ||
339 | pr_info("erasing block %d\n", ebnum); | 245 | pr_info("erasing block %d\n", ebnum); |
340 | err = erase_eraseblock(ebnum); | 246 | err = mtdtest_erase_eraseblock(mtd, ebnum); |
341 | if (err) | 247 | if (err) |
342 | return err; | 248 | return err; |
343 | 249 | ||
344 | pr_info("writing 1st page of block %d\n", ebnum); | 250 | pr_info("writing 1st page of block %d\n", ebnum); |
345 | prandom_bytes_state(&rnd_state, writebuf, pgsize); | 251 | prandom_bytes_state(&rnd_state, writebuf, pgsize); |
346 | strcpy(writebuf, "There is no data like this!"); | 252 | strcpy(writebuf, "There is no data like this!"); |
347 | err = mtd_write(mtd, addr0, pgsize, &written, writebuf); | 253 | err = mtdtest_write(mtd, addr0, pgsize, writebuf); |
348 | if (err || written != pgsize) { | 254 | if (err) |
349 | pr_err("error: write failed at %#llx\n", | 255 | return err; |
350 | (long long)addr0); | ||
351 | return err ? err : -1; | ||
352 | } | ||
353 | 256 | ||
354 | pr_info("erasing block %d\n", ebnum2); | 257 | pr_info("erasing block %d\n", ebnum2); |
355 | err = erase_eraseblock(ebnum2); | 258 | err = mtdtest_erase_eraseblock(mtd, ebnum2); |
356 | if (err) | 259 | if (err) |
357 | return err; | 260 | return err; |
358 | 261 | ||
359 | pr_info("reading 1st page of block %d\n", ebnum); | 262 | pr_info("reading 1st page of block %d\n", ebnum); |
360 | memset(readbuf, 0, pgsize); | 263 | memset(readbuf, 0, pgsize); |
361 | err = mtd_read(mtd, addr0, pgsize, &read, readbuf); | 264 | err = mtdtest_read(mtd, addr0, pgsize, readbuf); |
362 | if (mtd_is_bitflip(err)) | 265 | if (err) |
363 | err = 0; | 266 | return err; |
364 | if (err || read != pgsize) { | ||
365 | pr_err("error: read failed at %#llx\n", | ||
366 | (long long)addr0); | ||
367 | return err ? err : -1; | ||
368 | } | ||
369 | 267 | ||
370 | pr_info("verifying 1st page of block %d\n", ebnum); | 268 | pr_info("verifying 1st page of block %d\n", ebnum); |
371 | if (memcmp(writebuf, readbuf, pgsize)) { | 269 | if (memcmp(writebuf, readbuf, pgsize)) { |
@@ -381,7 +279,6 @@ static int erasecrosstest(void) | |||
381 | 279 | ||
382 | static int erasetest(void) | 280 | static int erasetest(void) |
383 | { | 281 | { |
384 | size_t read, written; | ||
385 | int err = 0, i, ebnum, ok = 1; | 282 | int err = 0, i, ebnum, ok = 1; |
386 | loff_t addr0; | 283 | loff_t addr0; |
387 | 284 | ||
@@ -395,33 +292,25 @@ static int erasetest(void) | |||
395 | } | 292 | } |
396 | 293 | ||
397 | pr_info("erasing block %d\n", ebnum); | 294 | pr_info("erasing block %d\n", ebnum); |
398 | err = erase_eraseblock(ebnum); | 295 | err = mtdtest_erase_eraseblock(mtd, ebnum); |
399 | if (err) | 296 | if (err) |
400 | return err; | 297 | return err; |
401 | 298 | ||
402 | pr_info("writing 1st page of block %d\n", ebnum); | 299 | pr_info("writing 1st page of block %d\n", ebnum); |
403 | prandom_bytes_state(&rnd_state, writebuf, pgsize); | 300 | prandom_bytes_state(&rnd_state, writebuf, pgsize); |
404 | err = mtd_write(mtd, addr0, pgsize, &written, writebuf); | 301 | err = mtdtest_write(mtd, addr0, pgsize, writebuf); |
405 | if (err || written != pgsize) { | 302 | if (err) |
406 | pr_err("error: write failed at %#llx\n", | 303 | return err; |
407 | (long long)addr0); | ||
408 | return err ? err : -1; | ||
409 | } | ||
410 | 304 | ||
411 | pr_info("erasing block %d\n", ebnum); | 305 | pr_info("erasing block %d\n", ebnum); |
412 | err = erase_eraseblock(ebnum); | 306 | err = mtdtest_erase_eraseblock(mtd, ebnum); |
413 | if (err) | 307 | if (err) |
414 | return err; | 308 | return err; |
415 | 309 | ||
416 | pr_info("reading 1st page of block %d\n", ebnum); | 310 | pr_info("reading 1st page of block %d\n", ebnum); |
417 | err = mtd_read(mtd, addr0, pgsize, &read, twopages); | 311 | err = mtdtest_read(mtd, addr0, pgsize, twopages); |
418 | if (mtd_is_bitflip(err)) | 312 | if (err) |
419 | err = 0; | 313 | return err; |
420 | if (err || read != pgsize) { | ||
421 | pr_err("error: read failed at %#llx\n", | ||
422 | (long long)addr0); | ||
423 | return err ? err : -1; | ||
424 | } | ||
425 | 314 | ||
426 | pr_info("verifying 1st page of block %d is all 0xff\n", | 315 | pr_info("verifying 1st page of block %d is all 0xff\n", |
427 | ebnum); | 316 | ebnum); |
@@ -440,38 +329,6 @@ static int erasetest(void) | |||
440 | return err; | 329 | return err; |
441 | } | 330 | } |
442 | 331 | ||
443 | static int is_block_bad(int ebnum) | ||
444 | { | ||
445 | loff_t addr = ebnum * mtd->erasesize; | ||
446 | int ret; | ||
447 | |||
448 | ret = mtd_block_isbad(mtd, addr); | ||
449 | if (ret) | ||
450 | pr_info("block %d is bad\n", ebnum); | ||
451 | return ret; | ||
452 | } | ||
453 | |||
454 | static int scan_for_bad_eraseblocks(void) | ||
455 | { | ||
456 | int i, bad = 0; | ||
457 | |||
458 | bbt = kzalloc(ebcnt, GFP_KERNEL); | ||
459 | if (!bbt) { | ||
460 | pr_err("error: cannot allocate memory\n"); | ||
461 | return -ENOMEM; | ||
462 | } | ||
463 | |||
464 | pr_info("scanning for bad eraseblocks\n"); | ||
465 | for (i = 0; i < ebcnt; ++i) { | ||
466 | bbt[i] = is_block_bad(i) ? 1 : 0; | ||
467 | if (bbt[i]) | ||
468 | bad += 1; | ||
469 | cond_resched(); | ||
470 | } | ||
471 | pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); | ||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | static int __init mtd_pagetest_init(void) | 332 | static int __init mtd_pagetest_init(void) |
476 | { | 333 | { |
477 | int err = 0; | 334 | int err = 0; |
@@ -516,36 +373,28 @@ static int __init mtd_pagetest_init(void) | |||
516 | err = -ENOMEM; | 373 | err = -ENOMEM; |
517 | bufsize = pgsize * 2; | 374 | bufsize = pgsize * 2; |
518 | writebuf = kmalloc(mtd->erasesize, GFP_KERNEL); | 375 | writebuf = kmalloc(mtd->erasesize, GFP_KERNEL); |
519 | if (!writebuf) { | 376 | if (!writebuf) |
520 | pr_err("error: cannot allocate memory\n"); | ||
521 | goto out; | 377 | goto out; |
522 | } | ||
523 | twopages = kmalloc(bufsize, GFP_KERNEL); | 378 | twopages = kmalloc(bufsize, GFP_KERNEL); |
524 | if (!twopages) { | 379 | if (!twopages) |
525 | pr_err("error: cannot allocate memory\n"); | ||
526 | goto out; | 380 | goto out; |
527 | } | ||
528 | boundary = kmalloc(bufsize, GFP_KERNEL); | 381 | boundary = kmalloc(bufsize, GFP_KERNEL); |
529 | if (!boundary) { | 382 | if (!boundary) |
530 | pr_err("error: cannot allocate memory\n"); | ||
531 | goto out; | 383 | goto out; |
532 | } | ||
533 | 384 | ||
534 | err = scan_for_bad_eraseblocks(); | 385 | bbt = kzalloc(ebcnt, GFP_KERNEL); |
386 | if (!bbt) | ||
387 | goto out; | ||
388 | err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt); | ||
535 | if (err) | 389 | if (err) |
536 | goto out; | 390 | goto out; |
537 | 391 | ||
538 | /* Erase all eraseblocks */ | 392 | /* Erase all eraseblocks */ |
539 | pr_info("erasing whole device\n"); | 393 | pr_info("erasing whole device\n"); |
540 | for (i = 0; i < ebcnt; ++i) { | 394 | err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); |
541 | if (bbt[i]) | 395 | if (err) |
542 | continue; | 396 | goto out; |
543 | err = erase_eraseblock(i); | 397 | pr_info("erased %u eraseblocks\n", ebcnt); |
544 | if (err) | ||
545 | goto out; | ||
546 | cond_resched(); | ||
547 | } | ||
548 | pr_info("erased %u eraseblocks\n", i); | ||
549 | 398 | ||
550 | /* Write all eraseblocks */ | 399 | /* Write all eraseblocks */ |
551 | prandom_seed_state(&rnd_state, 1); | 400 | prandom_seed_state(&rnd_state, 1); |
diff --git a/drivers/mtd/tests/mtd_readtest.c b/drivers/mtd/tests/readtest.c index 266de04b6d29..626e66d0f7e7 100644 --- a/drivers/mtd/tests/mtd_readtest.c +++ b/drivers/mtd/tests/readtest.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
31 | 31 | ||
32 | #include "mtd_test.h" | ||
33 | |||
32 | static int dev = -EINVAL; | 34 | static int dev = -EINVAL; |
33 | module_param(dev, int, S_IRUGO); | 35 | module_param(dev, int, S_IRUGO); |
34 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 36 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
@@ -44,7 +46,6 @@ static int pgcnt; | |||
44 | 46 | ||
45 | static int read_eraseblock_by_page(int ebnum) | 47 | static int read_eraseblock_by_page(int ebnum) |
46 | { | 48 | { |
47 | size_t read; | ||
48 | int i, ret, err = 0; | 49 | int i, ret, err = 0; |
49 | loff_t addr = ebnum * mtd->erasesize; | 50 | loff_t addr = ebnum * mtd->erasesize; |
50 | void *buf = iobuf; | 51 | void *buf = iobuf; |
@@ -52,16 +53,10 @@ static int read_eraseblock_by_page(int ebnum) | |||
52 | 53 | ||
53 | for (i = 0; i < pgcnt; i++) { | 54 | for (i = 0; i < pgcnt; i++) { |
54 | memset(buf, 0 , pgsize); | 55 | memset(buf, 0 , pgsize); |
55 | ret = mtd_read(mtd, addr, pgsize, &read, buf); | 56 | ret = mtdtest_read(mtd, addr, pgsize, buf); |
56 | if (ret == -EUCLEAN) | 57 | if (ret) { |
57 | ret = 0; | ||
58 | if (ret || read != pgsize) { | ||
59 | pr_err("error: read failed at %#llx\n", | ||
60 | (long long)addr); | ||
61 | if (!err) | 58 | if (!err) |
62 | err = ret; | 59 | err = ret; |
63 | if (!err) | ||
64 | err = -EINVAL; | ||
65 | } | 60 | } |
66 | if (mtd->oobsize) { | 61 | if (mtd->oobsize) { |
67 | struct mtd_oob_ops ops; | 62 | struct mtd_oob_ops ops; |
@@ -127,41 +122,6 @@ static void dump_eraseblock(int ebnum) | |||
127 | } | 122 | } |
128 | } | 123 | } |
129 | 124 | ||
130 | static int is_block_bad(int ebnum) | ||
131 | { | ||
132 | loff_t addr = ebnum * mtd->erasesize; | ||
133 | int ret; | ||
134 | |||
135 | ret = mtd_block_isbad(mtd, addr); | ||
136 | if (ret) | ||
137 | pr_info("block %d is bad\n", ebnum); | ||
138 | return ret; | ||
139 | } | ||
140 | |||
141 | static int scan_for_bad_eraseblocks(void) | ||
142 | { | ||
143 | int i, bad = 0; | ||
144 | |||
145 | bbt = kzalloc(ebcnt, GFP_KERNEL); | ||
146 | if (!bbt) { | ||
147 | pr_err("error: cannot allocate memory\n"); | ||
148 | return -ENOMEM; | ||
149 | } | ||
150 | |||
151 | if (!mtd_can_have_bb(mtd)) | ||
152 | return 0; | ||
153 | |||
154 | pr_info("scanning for bad eraseblocks\n"); | ||
155 | for (i = 0; i < ebcnt; ++i) { | ||
156 | bbt[i] = is_block_bad(i) ? 1 : 0; | ||
157 | if (bbt[i]) | ||
158 | bad += 1; | ||
159 | cond_resched(); | ||
160 | } | ||
161 | pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static int __init mtd_readtest_init(void) | 125 | static int __init mtd_readtest_init(void) |
166 | { | 126 | { |
167 | uint64_t tmp; | 127 | uint64_t tmp; |
@@ -204,17 +164,16 @@ static int __init mtd_readtest_init(void) | |||
204 | 164 | ||
205 | err = -ENOMEM; | 165 | err = -ENOMEM; |
206 | iobuf = kmalloc(mtd->erasesize, GFP_KERNEL); | 166 | iobuf = kmalloc(mtd->erasesize, GFP_KERNEL); |
207 | if (!iobuf) { | 167 | if (!iobuf) |
208 | pr_err("error: cannot allocate memory\n"); | ||
209 | goto out; | 168 | goto out; |
210 | } | ||
211 | iobuf1 = kmalloc(mtd->erasesize, GFP_KERNEL); | 169 | iobuf1 = kmalloc(mtd->erasesize, GFP_KERNEL); |
212 | if (!iobuf1) { | 170 | if (!iobuf1) |
213 | pr_err("error: cannot allocate memory\n"); | ||
214 | goto out; | 171 | goto out; |
215 | } | ||
216 | 172 | ||
217 | err = scan_for_bad_eraseblocks(); | 173 | bbt = kzalloc(ebcnt, GFP_KERNEL); |
174 | if (!bbt) | ||
175 | goto out; | ||
176 | err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt); | ||
218 | if (err) | 177 | if (err) |
219 | goto out; | 178 | goto out; |
220 | 179 | ||
diff --git a/drivers/mtd/tests/mtd_speedtest.c b/drivers/mtd/tests/speedtest.c index a6ce9c1fa6c5..87ff6a29f84e 100644 --- a/drivers/mtd/tests/mtd_speedtest.c +++ b/drivers/mtd/tests/speedtest.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
31 | #include <linux/random.h> | 31 | #include <linux/random.h> |
32 | 32 | ||
33 | #include "mtd_test.h" | ||
34 | |||
33 | static int dev = -EINVAL; | 35 | static int dev = -EINVAL; |
34 | module_param(dev, int, S_IRUGO); | 36 | module_param(dev, int, S_IRUGO); |
35 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 37 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
@@ -49,33 +51,6 @@ static int pgcnt; | |||
49 | static int goodebcnt; | 51 | static int goodebcnt; |
50 | static struct timeval start, finish; | 52 | static struct timeval start, finish; |
51 | 53 | ||
52 | |||
53 | static int erase_eraseblock(int ebnum) | ||
54 | { | ||
55 | int err; | ||
56 | struct erase_info ei; | ||
57 | loff_t addr = ebnum * mtd->erasesize; | ||
58 | |||
59 | memset(&ei, 0, sizeof(struct erase_info)); | ||
60 | ei.mtd = mtd; | ||
61 | ei.addr = addr; | ||
62 | ei.len = mtd->erasesize; | ||
63 | |||
64 | err = mtd_erase(mtd, &ei); | ||
65 | if (err) { | ||
66 | pr_err("error %d while erasing EB %d\n", err, ebnum); | ||
67 | return err; | ||
68 | } | ||
69 | |||
70 | if (ei.state == MTD_ERASE_FAILED) { | ||
71 | pr_err("some erase error occurred at EB %d\n", | ||
72 | ebnum); | ||
73 | return -EIO; | ||
74 | } | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int multiblock_erase(int ebnum, int blocks) | 54 | static int multiblock_erase(int ebnum, int blocks) |
80 | { | 55 | { |
81 | int err; | 56 | int err; |
@@ -103,54 +78,23 @@ static int multiblock_erase(int ebnum, int blocks) | |||
103 | return 0; | 78 | return 0; |
104 | } | 79 | } |
105 | 80 | ||
106 | static int erase_whole_device(void) | ||
107 | { | ||
108 | int err; | ||
109 | unsigned int i; | ||
110 | |||
111 | for (i = 0; i < ebcnt; ++i) { | ||
112 | if (bbt[i]) | ||
113 | continue; | ||
114 | err = erase_eraseblock(i); | ||
115 | if (err) | ||
116 | return err; | ||
117 | cond_resched(); | ||
118 | } | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static int write_eraseblock(int ebnum) | 81 | static int write_eraseblock(int ebnum) |
123 | { | 82 | { |
124 | size_t written; | ||
125 | int err = 0; | ||
126 | loff_t addr = ebnum * mtd->erasesize; | 83 | loff_t addr = ebnum * mtd->erasesize; |
127 | 84 | ||
128 | err = mtd_write(mtd, addr, mtd->erasesize, &written, iobuf); | 85 | return mtdtest_write(mtd, addr, mtd->erasesize, iobuf); |
129 | if (err || written != mtd->erasesize) { | ||
130 | pr_err("error: write failed at %#llx\n", addr); | ||
131 | if (!err) | ||
132 | err = -EINVAL; | ||
133 | } | ||
134 | |||
135 | return err; | ||
136 | } | 86 | } |
137 | 87 | ||
138 | static int write_eraseblock_by_page(int ebnum) | 88 | static int write_eraseblock_by_page(int ebnum) |
139 | { | 89 | { |
140 | size_t written; | ||
141 | int i, err = 0; | 90 | int i, err = 0; |
142 | loff_t addr = ebnum * mtd->erasesize; | 91 | loff_t addr = ebnum * mtd->erasesize; |
143 | void *buf = iobuf; | 92 | void *buf = iobuf; |
144 | 93 | ||
145 | for (i = 0; i < pgcnt; i++) { | 94 | for (i = 0; i < pgcnt; i++) { |
146 | err = mtd_write(mtd, addr, pgsize, &written, buf); | 95 | err = mtdtest_write(mtd, addr, pgsize, buf); |
147 | if (err || written != pgsize) { | 96 | if (err) |
148 | pr_err("error: write failed at %#llx\n", | ||
149 | addr); | ||
150 | if (!err) | ||
151 | err = -EINVAL; | ||
152 | break; | 97 | break; |
153 | } | ||
154 | addr += pgsize; | 98 | addr += pgsize; |
155 | buf += pgsize; | 99 | buf += pgsize; |
156 | } | 100 | } |
@@ -160,74 +104,41 @@ static int write_eraseblock_by_page(int ebnum) | |||
160 | 104 | ||
161 | static int write_eraseblock_by_2pages(int ebnum) | 105 | static int write_eraseblock_by_2pages(int ebnum) |
162 | { | 106 | { |
163 | size_t written, sz = pgsize * 2; | 107 | size_t sz = pgsize * 2; |
164 | int i, n = pgcnt / 2, err = 0; | 108 | int i, n = pgcnt / 2, err = 0; |
165 | loff_t addr = ebnum * mtd->erasesize; | 109 | loff_t addr = ebnum * mtd->erasesize; |
166 | void *buf = iobuf; | 110 | void *buf = iobuf; |
167 | 111 | ||
168 | for (i = 0; i < n; i++) { | 112 | for (i = 0; i < n; i++) { |
169 | err = mtd_write(mtd, addr, sz, &written, buf); | 113 | err = mtdtest_write(mtd, addr, sz, buf); |
170 | if (err || written != sz) { | 114 | if (err) |
171 | pr_err("error: write failed at %#llx\n", | ||
172 | addr); | ||
173 | if (!err) | ||
174 | err = -EINVAL; | ||
175 | return err; | 115 | return err; |
176 | } | ||
177 | addr += sz; | 116 | addr += sz; |
178 | buf += sz; | 117 | buf += sz; |
179 | } | 118 | } |
180 | if (pgcnt % 2) { | 119 | if (pgcnt % 2) |
181 | err = mtd_write(mtd, addr, pgsize, &written, buf); | 120 | err = mtdtest_write(mtd, addr, pgsize, buf); |
182 | if (err || written != pgsize) { | ||
183 | pr_err("error: write failed at %#llx\n", | ||
184 | addr); | ||
185 | if (!err) | ||
186 | err = -EINVAL; | ||
187 | } | ||
188 | } | ||
189 | 121 | ||
190 | return err; | 122 | return err; |
191 | } | 123 | } |
192 | 124 | ||
193 | static int read_eraseblock(int ebnum) | 125 | static int read_eraseblock(int ebnum) |
194 | { | 126 | { |
195 | size_t read; | ||
196 | int err = 0; | ||
197 | loff_t addr = ebnum * mtd->erasesize; | 127 | loff_t addr = ebnum * mtd->erasesize; |
198 | 128 | ||
199 | err = mtd_read(mtd, addr, mtd->erasesize, &read, iobuf); | 129 | return mtdtest_read(mtd, addr, mtd->erasesize, iobuf); |
200 | /* Ignore corrected ECC errors */ | ||
201 | if (mtd_is_bitflip(err)) | ||
202 | err = 0; | ||
203 | if (err || read != mtd->erasesize) { | ||
204 | pr_err("error: read failed at %#llx\n", addr); | ||
205 | if (!err) | ||
206 | err = -EINVAL; | ||
207 | } | ||
208 | |||
209 | return err; | ||
210 | } | 130 | } |
211 | 131 | ||
212 | static int read_eraseblock_by_page(int ebnum) | 132 | static int read_eraseblock_by_page(int ebnum) |
213 | { | 133 | { |
214 | size_t read; | ||
215 | int i, err = 0; | 134 | int i, err = 0; |
216 | loff_t addr = ebnum * mtd->erasesize; | 135 | loff_t addr = ebnum * mtd->erasesize; |
217 | void *buf = iobuf; | 136 | void *buf = iobuf; |
218 | 137 | ||
219 | for (i = 0; i < pgcnt; i++) { | 138 | for (i = 0; i < pgcnt; i++) { |
220 | err = mtd_read(mtd, addr, pgsize, &read, buf); | 139 | err = mtdtest_read(mtd, addr, pgsize, buf); |
221 | /* Ignore corrected ECC errors */ | 140 | if (err) |
222 | if (mtd_is_bitflip(err)) | ||
223 | err = 0; | ||
224 | if (err || read != pgsize) { | ||
225 | pr_err("error: read failed at %#llx\n", | ||
226 | addr); | ||
227 | if (!err) | ||
228 | err = -EINVAL; | ||
229 | break; | 141 | break; |
230 | } | ||
231 | addr += pgsize; | 142 | addr += pgsize; |
232 | buf += pgsize; | 143 | buf += pgsize; |
233 | } | 144 | } |
@@ -237,53 +148,24 @@ static int read_eraseblock_by_page(int ebnum) | |||
237 | 148 | ||
238 | static int read_eraseblock_by_2pages(int ebnum) | 149 | static int read_eraseblock_by_2pages(int ebnum) |
239 | { | 150 | { |
240 | size_t read, sz = pgsize * 2; | 151 | size_t sz = pgsize * 2; |
241 | int i, n = pgcnt / 2, err = 0; | 152 | int i, n = pgcnt / 2, err = 0; |
242 | loff_t addr = ebnum * mtd->erasesize; | 153 | loff_t addr = ebnum * mtd->erasesize; |
243 | void *buf = iobuf; | 154 | void *buf = iobuf; |
244 | 155 | ||
245 | for (i = 0; i < n; i++) { | 156 | for (i = 0; i < n; i++) { |
246 | err = mtd_read(mtd, addr, sz, &read, buf); | 157 | err = mtdtest_read(mtd, addr, sz, buf); |
247 | /* Ignore corrected ECC errors */ | 158 | if (err) |
248 | if (mtd_is_bitflip(err)) | ||
249 | err = 0; | ||
250 | if (err || read != sz) { | ||
251 | pr_err("error: read failed at %#llx\n", | ||
252 | addr); | ||
253 | if (!err) | ||
254 | err = -EINVAL; | ||
255 | return err; | 159 | return err; |
256 | } | ||
257 | addr += sz; | 160 | addr += sz; |
258 | buf += sz; | 161 | buf += sz; |
259 | } | 162 | } |
260 | if (pgcnt % 2) { | 163 | if (pgcnt % 2) |
261 | err = mtd_read(mtd, addr, pgsize, &read, buf); | 164 | err = mtdtest_read(mtd, addr, pgsize, buf); |
262 | /* Ignore corrected ECC errors */ | ||
263 | if (mtd_is_bitflip(err)) | ||
264 | err = 0; | ||
265 | if (err || read != pgsize) { | ||
266 | pr_err("error: read failed at %#llx\n", | ||
267 | addr); | ||
268 | if (!err) | ||
269 | err = -EINVAL; | ||
270 | } | ||
271 | } | ||
272 | 165 | ||
273 | return err; | 166 | return err; |
274 | } | 167 | } |
275 | 168 | ||
276 | static int is_block_bad(int ebnum) | ||
277 | { | ||
278 | loff_t addr = ebnum * mtd->erasesize; | ||
279 | int ret; | ||
280 | |||
281 | ret = mtd_block_isbad(mtd, addr); | ||
282 | if (ret) | ||
283 | pr_info("block %d is bad\n", ebnum); | ||
284 | return ret; | ||
285 | } | ||
286 | |||
287 | static inline void start_timing(void) | 169 | static inline void start_timing(void) |
288 | { | 170 | { |
289 | do_gettimeofday(&start); | 171 | do_gettimeofday(&start); |
@@ -308,32 +190,6 @@ static long calc_speed(void) | |||
308 | return k; | 190 | return k; |
309 | } | 191 | } |
310 | 192 | ||
311 | static int scan_for_bad_eraseblocks(void) | ||
312 | { | ||
313 | int i, bad = 0; | ||
314 | |||
315 | bbt = kzalloc(ebcnt, GFP_KERNEL); | ||
316 | if (!bbt) { | ||
317 | pr_err("error: cannot allocate memory\n"); | ||
318 | return -ENOMEM; | ||
319 | } | ||
320 | |||
321 | if (!mtd_can_have_bb(mtd)) | ||
322 | goto out; | ||
323 | |||
324 | pr_info("scanning for bad eraseblocks\n"); | ||
325 | for (i = 0; i < ebcnt; ++i) { | ||
326 | bbt[i] = is_block_bad(i) ? 1 : 0; | ||
327 | if (bbt[i]) | ||
328 | bad += 1; | ||
329 | cond_resched(); | ||
330 | } | ||
331 | pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); | ||
332 | out: | ||
333 | goodebcnt = ebcnt - bad; | ||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | static int __init mtd_speedtest_init(void) | 193 | static int __init mtd_speedtest_init(void) |
338 | { | 194 | { |
339 | int err, i, blocks, j, k; | 195 | int err, i, blocks, j, k; |
@@ -384,18 +240,23 @@ static int __init mtd_speedtest_init(void) | |||
384 | 240 | ||
385 | err = -ENOMEM; | 241 | err = -ENOMEM; |
386 | iobuf = kmalloc(mtd->erasesize, GFP_KERNEL); | 242 | iobuf = kmalloc(mtd->erasesize, GFP_KERNEL); |
387 | if (!iobuf) { | 243 | if (!iobuf) |
388 | pr_err("error: cannot allocate memory\n"); | ||
389 | goto out; | 244 | goto out; |
390 | } | ||
391 | 245 | ||
392 | prandom_bytes(iobuf, mtd->erasesize); | 246 | prandom_bytes(iobuf, mtd->erasesize); |
393 | 247 | ||
394 | err = scan_for_bad_eraseblocks(); | 248 | bbt = kzalloc(ebcnt, GFP_KERNEL); |
249 | if (!bbt) | ||
250 | goto out; | ||
251 | err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt); | ||
395 | if (err) | 252 | if (err) |
396 | goto out; | 253 | goto out; |
254 | for (i = 0; i < ebcnt; i++) { | ||
255 | if (!bbt[i]) | ||
256 | goodebcnt++; | ||
257 | } | ||
397 | 258 | ||
398 | err = erase_whole_device(); | 259 | err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); |
399 | if (err) | 260 | if (err) |
400 | goto out; | 261 | goto out; |
401 | 262 | ||
@@ -429,7 +290,7 @@ static int __init mtd_speedtest_init(void) | |||
429 | speed = calc_speed(); | 290 | speed = calc_speed(); |
430 | pr_info("eraseblock read speed is %ld KiB/s\n", speed); | 291 | pr_info("eraseblock read speed is %ld KiB/s\n", speed); |
431 | 292 | ||
432 | err = erase_whole_device(); | 293 | err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); |
433 | if (err) | 294 | if (err) |
434 | goto out; | 295 | goto out; |
435 | 296 | ||
@@ -463,7 +324,7 @@ static int __init mtd_speedtest_init(void) | |||
463 | speed = calc_speed(); | 324 | speed = calc_speed(); |
464 | pr_info("page read speed is %ld KiB/s\n", speed); | 325 | pr_info("page read speed is %ld KiB/s\n", speed); |
465 | 326 | ||
466 | err = erase_whole_device(); | 327 | err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); |
467 | if (err) | 328 | if (err) |
468 | goto out; | 329 | goto out; |
469 | 330 | ||
@@ -500,14 +361,9 @@ static int __init mtd_speedtest_init(void) | |||
500 | /* Erase all eraseblocks */ | 361 | /* Erase all eraseblocks */ |
501 | pr_info("Testing erase speed\n"); | 362 | pr_info("Testing erase speed\n"); |
502 | start_timing(); | 363 | start_timing(); |
503 | for (i = 0; i < ebcnt; ++i) { | 364 | err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); |
504 | if (bbt[i]) | 365 | if (err) |
505 | continue; | 366 | goto out; |
506 | err = erase_eraseblock(i); | ||
507 | if (err) | ||
508 | goto out; | ||
509 | cond_resched(); | ||
510 | } | ||
511 | stop_timing(); | 367 | stop_timing(); |
512 | speed = calc_speed(); | 368 | speed = calc_speed(); |
513 | pr_info("erase speed is %ld KiB/s\n", speed); | 369 | pr_info("erase speed is %ld KiB/s\n", speed); |
diff --git a/drivers/mtd/tests/mtd_stresstest.c b/drivers/mtd/tests/stresstest.c index 787f539d16ca..c9d42cc2df1b 100644 --- a/drivers/mtd/tests/mtd_stresstest.c +++ b/drivers/mtd/tests/stresstest.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/vmalloc.h> | 31 | #include <linux/vmalloc.h> |
32 | #include <linux/random.h> | 32 | #include <linux/random.h> |
33 | 33 | ||
34 | #include "mtd_test.h" | ||
35 | |||
34 | static int dev = -EINVAL; | 36 | static int dev = -EINVAL; |
35 | module_param(dev, int, S_IRUGO); | 37 | module_param(dev, int, S_IRUGO); |
36 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 38 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
@@ -81,49 +83,11 @@ static int rand_len(int offs) | |||
81 | return len; | 83 | return len; |
82 | } | 84 | } |
83 | 85 | ||
84 | static int erase_eraseblock(int ebnum) | ||
85 | { | ||
86 | int err; | ||
87 | struct erase_info ei; | ||
88 | loff_t addr = ebnum * mtd->erasesize; | ||
89 | |||
90 | memset(&ei, 0, sizeof(struct erase_info)); | ||
91 | ei.mtd = mtd; | ||
92 | ei.addr = addr; | ||
93 | ei.len = mtd->erasesize; | ||
94 | |||
95 | err = mtd_erase(mtd, &ei); | ||
96 | if (unlikely(err)) { | ||
97 | pr_err("error %d while erasing EB %d\n", err, ebnum); | ||
98 | return err; | ||
99 | } | ||
100 | |||
101 | if (unlikely(ei.state == MTD_ERASE_FAILED)) { | ||
102 | pr_err("some erase error occurred at EB %d\n", | ||
103 | ebnum); | ||
104 | return -EIO; | ||
105 | } | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static int is_block_bad(int ebnum) | ||
111 | { | ||
112 | loff_t addr = ebnum * mtd->erasesize; | ||
113 | int ret; | ||
114 | |||
115 | ret = mtd_block_isbad(mtd, addr); | ||
116 | if (ret) | ||
117 | pr_info("block %d is bad\n", ebnum); | ||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | static int do_read(void) | 86 | static int do_read(void) |
122 | { | 87 | { |
123 | size_t read; | ||
124 | int eb = rand_eb(); | 88 | int eb = rand_eb(); |
125 | int offs = rand_offs(); | 89 | int offs = rand_offs(); |
126 | int len = rand_len(offs), err; | 90 | int len = rand_len(offs); |
127 | loff_t addr; | 91 | loff_t addr; |
128 | 92 | ||
129 | if (bbt[eb + 1]) { | 93 | if (bbt[eb + 1]) { |
@@ -133,28 +97,17 @@ static int do_read(void) | |||
133 | len = mtd->erasesize - offs; | 97 | len = mtd->erasesize - offs; |
134 | } | 98 | } |
135 | addr = eb * mtd->erasesize + offs; | 99 | addr = eb * mtd->erasesize + offs; |
136 | err = mtd_read(mtd, addr, len, &read, readbuf); | 100 | return mtdtest_read(mtd, addr, len, readbuf); |
137 | if (mtd_is_bitflip(err)) | ||
138 | err = 0; | ||
139 | if (unlikely(err || read != len)) { | ||
140 | pr_err("error: read failed at 0x%llx\n", | ||
141 | (long long)addr); | ||
142 | if (!err) | ||
143 | err = -EINVAL; | ||
144 | return err; | ||
145 | } | ||
146 | return 0; | ||
147 | } | 101 | } |
148 | 102 | ||
149 | static int do_write(void) | 103 | static int do_write(void) |
150 | { | 104 | { |
151 | int eb = rand_eb(), offs, err, len; | 105 | int eb = rand_eb(), offs, err, len; |
152 | size_t written; | ||
153 | loff_t addr; | 106 | loff_t addr; |
154 | 107 | ||
155 | offs = offsets[eb]; | 108 | offs = offsets[eb]; |
156 | if (offs >= mtd->erasesize) { | 109 | if (offs >= mtd->erasesize) { |
157 | err = erase_eraseblock(eb); | 110 | err = mtdtest_erase_eraseblock(mtd, eb); |
158 | if (err) | 111 | if (err) |
159 | return err; | 112 | return err; |
160 | offs = offsets[eb] = 0; | 113 | offs = offsets[eb] = 0; |
@@ -165,21 +118,16 @@ static int do_write(void) | |||
165 | if (bbt[eb + 1]) | 118 | if (bbt[eb + 1]) |
166 | len = mtd->erasesize - offs; | 119 | len = mtd->erasesize - offs; |
167 | else { | 120 | else { |
168 | err = erase_eraseblock(eb + 1); | 121 | err = mtdtest_erase_eraseblock(mtd, eb + 1); |
169 | if (err) | 122 | if (err) |
170 | return err; | 123 | return err; |
171 | offsets[eb + 1] = 0; | 124 | offsets[eb + 1] = 0; |
172 | } | 125 | } |
173 | } | 126 | } |
174 | addr = eb * mtd->erasesize + offs; | 127 | addr = eb * mtd->erasesize + offs; |
175 | err = mtd_write(mtd, addr, len, &written, writebuf); | 128 | err = mtdtest_write(mtd, addr, len, writebuf); |
176 | if (unlikely(err || written != len)) { | 129 | if (unlikely(err)) |
177 | pr_err("error: write failed at 0x%llx\n", | ||
178 | (long long)addr); | ||
179 | if (!err) | ||
180 | err = -EINVAL; | ||
181 | return err; | 130 | return err; |
182 | } | ||
183 | offs += len; | 131 | offs += len; |
184 | while (offs > mtd->erasesize) { | 132 | while (offs > mtd->erasesize) { |
185 | offsets[eb++] = mtd->erasesize; | 133 | offsets[eb++] = mtd->erasesize; |
@@ -197,30 +145,6 @@ static int do_operation(void) | |||
197 | return do_write(); | 145 | return do_write(); |
198 | } | 146 | } |
199 | 147 | ||
200 | static int scan_for_bad_eraseblocks(void) | ||
201 | { | ||
202 | int i, bad = 0; | ||
203 | |||
204 | bbt = kzalloc(ebcnt, GFP_KERNEL); | ||
205 | if (!bbt) { | ||
206 | pr_err("error: cannot allocate memory\n"); | ||
207 | return -ENOMEM; | ||
208 | } | ||
209 | |||
210 | if (!mtd_can_have_bb(mtd)) | ||
211 | return 0; | ||
212 | |||
213 | pr_info("scanning for bad eraseblocks\n"); | ||
214 | for (i = 0; i < ebcnt; ++i) { | ||
215 | bbt[i] = is_block_bad(i) ? 1 : 0; | ||
216 | if (bbt[i]) | ||
217 | bad += 1; | ||
218 | cond_resched(); | ||
219 | } | ||
220 | pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); | ||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static int __init mtd_stresstest_init(void) | 148 | static int __init mtd_stresstest_init(void) |
225 | { | 149 | { |
226 | int err; | 150 | int err; |
@@ -276,15 +200,16 @@ static int __init mtd_stresstest_init(void) | |||
276 | readbuf = vmalloc(bufsize); | 200 | readbuf = vmalloc(bufsize); |
277 | writebuf = vmalloc(bufsize); | 201 | writebuf = vmalloc(bufsize); |
278 | offsets = kmalloc(ebcnt * sizeof(int), GFP_KERNEL); | 202 | offsets = kmalloc(ebcnt * sizeof(int), GFP_KERNEL); |
279 | if (!readbuf || !writebuf || !offsets) { | 203 | if (!readbuf || !writebuf || !offsets) |
280 | pr_err("error: cannot allocate memory\n"); | ||
281 | goto out; | 204 | goto out; |
282 | } | ||
283 | for (i = 0; i < ebcnt; i++) | 205 | for (i = 0; i < ebcnt; i++) |
284 | offsets[i] = mtd->erasesize; | 206 | offsets[i] = mtd->erasesize; |
285 | prandom_bytes(writebuf, bufsize); | 207 | prandom_bytes(writebuf, bufsize); |
286 | 208 | ||
287 | err = scan_for_bad_eraseblocks(); | 209 | bbt = kzalloc(ebcnt, GFP_KERNEL); |
210 | if (!bbt) | ||
211 | goto out; | ||
212 | err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt); | ||
288 | if (err) | 213 | if (err) |
289 | goto out; | 214 | goto out; |
290 | 215 | ||
diff --git a/drivers/mtd/tests/mtd_subpagetest.c b/drivers/mtd/tests/subpagetest.c index aade56f27945..e2c0adf24cfc 100644 --- a/drivers/mtd/tests/mtd_subpagetest.c +++ b/drivers/mtd/tests/subpagetest.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
31 | #include <linux/random.h> | 31 | #include <linux/random.h> |
32 | 32 | ||
33 | #include "mtd_test.h" | ||
34 | |||
33 | static int dev = -EINVAL; | 35 | static int dev = -EINVAL; |
34 | module_param(dev, int, S_IRUGO); | 36 | module_param(dev, int, S_IRUGO); |
35 | MODULE_PARM_DESC(dev, "MTD device number to use"); | 37 | MODULE_PARM_DESC(dev, "MTD device number to use"); |
@@ -51,50 +53,6 @@ static inline void clear_data(unsigned char *buf, size_t len) | |||
51 | memset(buf, 0, len); | 53 | memset(buf, 0, len); |
52 | } | 54 | } |
53 | 55 | ||
54 | static int erase_eraseblock(int ebnum) | ||
55 | { | ||
56 | int err; | ||
57 | struct erase_info ei; | ||
58 | loff_t addr = ebnum * mtd->erasesize; | ||
59 | |||
60 | memset(&ei, 0, sizeof(struct erase_info)); | ||
61 | ei.mtd = mtd; | ||
62 | ei.addr = addr; | ||
63 | ei.len = mtd->erasesize; | ||
64 | |||
65 | err = mtd_erase(mtd, &ei); | ||
66 | if (err) { | ||
67 | pr_err("error %d while erasing EB %d\n", err, ebnum); | ||
68 | return err; | ||
69 | } | ||
70 | |||
71 | if (ei.state == MTD_ERASE_FAILED) { | ||
72 | pr_err("some erase error occurred at EB %d\n", | ||
73 | ebnum); | ||
74 | return -EIO; | ||
75 | } | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static int erase_whole_device(void) | ||
81 | { | ||
82 | int err; | ||
83 | unsigned int i; | ||
84 | |||
85 | pr_info("erasing whole device\n"); | ||
86 | for (i = 0; i < ebcnt; ++i) { | ||
87 | if (bbt[i]) | ||
88 | continue; | ||
89 | err = erase_eraseblock(i); | ||
90 | if (err) | ||
91 | return err; | ||
92 | cond_resched(); | ||
93 | } | ||
94 | pr_info("erased %u eraseblocks\n", i); | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static int write_eraseblock(int ebnum) | 56 | static int write_eraseblock(int ebnum) |
99 | { | 57 | { |
100 | size_t written; | 58 | size_t written; |
@@ -317,38 +275,6 @@ static int verify_all_eraseblocks_ff(void) | |||
317 | return 0; | 275 | return 0; |
318 | } | 276 | } |
319 | 277 | ||
320 | static int is_block_bad(int ebnum) | ||
321 | { | ||
322 | loff_t addr = ebnum * mtd->erasesize; | ||
323 | int ret; | ||
324 | |||
325 | ret = mtd_block_isbad(mtd, addr); | ||
326 | if (ret) | ||
327 | pr_info("block %d is bad\n", ebnum); | ||
328 | return ret; | ||
329 | } | ||
330 | |||
331 | static int scan_for_bad_eraseblocks(void) | ||
332 | { | ||
333 | int i, bad = 0; | ||
334 | |||
335 | bbt = kzalloc(ebcnt, GFP_KERNEL); | ||
336 | if (!bbt) { | ||
337 | pr_err("error: cannot allocate memory\n"); | ||
338 | return -ENOMEM; | ||
339 | } | ||
340 | |||
341 | pr_info("scanning for bad eraseblocks\n"); | ||
342 | for (i = 0; i < ebcnt; ++i) { | ||
343 | bbt[i] = is_block_bad(i) ? 1 : 0; | ||
344 | if (bbt[i]) | ||
345 | bad += 1; | ||
346 | cond_resched(); | ||
347 | } | ||
348 | pr_info("scanned %d eraseblocks, %d are bad\n", i, bad); | ||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | static int __init mtd_subpagetest_init(void) | 278 | static int __init mtd_subpagetest_init(void) |
353 | { | 279 | { |
354 | int err = 0; | 280 | int err = 0; |
@@ -393,21 +319,20 @@ static int __init mtd_subpagetest_init(void) | |||
393 | err = -ENOMEM; | 319 | err = -ENOMEM; |
394 | bufsize = subpgsize * 32; | 320 | bufsize = subpgsize * 32; |
395 | writebuf = kmalloc(bufsize, GFP_KERNEL); | 321 | writebuf = kmalloc(bufsize, GFP_KERNEL); |
396 | if (!writebuf) { | 322 | if (!writebuf) |
397 | pr_info("error: cannot allocate memory\n"); | ||
398 | goto out; | 323 | goto out; |
399 | } | ||
400 | readbuf = kmalloc(bufsize, GFP_KERNEL); | 324 | readbuf = kmalloc(bufsize, GFP_KERNEL); |
401 | if (!readbuf) { | 325 | if (!readbuf) |
402 | pr_info("error: cannot allocate memory\n"); | 326 | goto out; |
327 | bbt = kzalloc(ebcnt, GFP_KERNEL); | ||
328 | if (!bbt) | ||
403 | goto out; | 329 | goto out; |
404 | } | ||
405 | 330 | ||
406 | err = scan_for_bad_eraseblocks(); | 331 | err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt); |
407 | if (err) | 332 | if (err) |
408 | goto out; | 333 | goto out; |
409 | 334 | ||
410 | err = erase_whole_device(); | 335 | err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); |
411 | if (err) | 336 | if (err) |
412 | goto out; | 337 | goto out; |
413 | 338 | ||
@@ -439,7 +364,7 @@ static int __init mtd_subpagetest_init(void) | |||
439 | } | 364 | } |
440 | pr_info("verified %u eraseblocks\n", i); | 365 | pr_info("verified %u eraseblocks\n", i); |
441 | 366 | ||
442 | err = erase_whole_device(); | 367 | err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); |
443 | if (err) | 368 | if (err) |
444 | goto out; | 369 | goto out; |
445 | 370 | ||
@@ -477,7 +402,7 @@ static int __init mtd_subpagetest_init(void) | |||
477 | } | 402 | } |
478 | pr_info("verified %u eraseblocks\n", i); | 403 | pr_info("verified %u eraseblocks\n", i); |
479 | 404 | ||
480 | err = erase_whole_device(); | 405 | err = mtdtest_erase_good_eraseblocks(mtd, bbt, 0, ebcnt); |
481 | if (err) | 406 | if (err) |
482 | goto out; | 407 | goto out; |
483 | 408 | ||
diff --git a/drivers/mtd/tests/mtd_torturetest.c b/drivers/mtd/tests/torturetest.c index 3a9f6a6a79f9..eeab96973cf0 100644 --- a/drivers/mtd/tests/mtd_torturetest.c +++ b/drivers/mtd/tests/torturetest.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/mtd/mtd.h> | 32 | #include <linux/mtd/mtd.h> |
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/sched.h> | 34 | #include <linux/sched.h> |
35 | #include "mtd_test.h" | ||
35 | 36 | ||
36 | #define RETRIES 3 | 37 | #define RETRIES 3 |
37 | 38 | ||
@@ -93,35 +94,6 @@ static inline void stop_timing(void) | |||
93 | } | 94 | } |
94 | 95 | ||
95 | /* | 96 | /* |
96 | * Erase eraseblock number @ebnum. | ||
97 | */ | ||
98 | static inline int erase_eraseblock(int ebnum) | ||
99 | { | ||
100 | int err; | ||
101 | struct erase_info ei; | ||
102 | loff_t addr = ebnum * mtd->erasesize; | ||
103 | |||
104 | memset(&ei, 0, sizeof(struct erase_info)); | ||
105 | ei.mtd = mtd; | ||
106 | ei.addr = addr; | ||
107 | ei.len = mtd->erasesize; | ||
108 | |||
109 | err = mtd_erase(mtd, &ei); | ||
110 | if (err) { | ||
111 | pr_err("error %d while erasing EB %d\n", err, ebnum); | ||
112 | return err; | ||
113 | } | ||
114 | |||
115 | if (ei.state == MTD_ERASE_FAILED) { | ||
116 | pr_err("some erase error occurred at EB %d\n", | ||
117 | ebnum); | ||
118 | return -EIO; | ||
119 | } | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | /* | ||
125 | * Check that the contents of eraseblock number @enbum is equivalent to the | 97 | * Check that the contents of eraseblock number @enbum is equivalent to the |
126 | * @buf buffer. | 98 | * @buf buffer. |
127 | */ | 99 | */ |
@@ -208,7 +180,7 @@ static inline int write_pattern(int ebnum, void *buf) | |||
208 | static int __init tort_init(void) | 180 | static int __init tort_init(void) |
209 | { | 181 | { |
210 | int err = 0, i, infinite = !cycles_count; | 182 | int err = 0, i, infinite = !cycles_count; |
211 | int *bad_ebs; | 183 | unsigned char *bad_ebs; |
212 | 184 | ||
213 | printk(KERN_INFO "\n"); | 185 | printk(KERN_INFO "\n"); |
214 | printk(KERN_INFO "=================================================\n"); | 186 | printk(KERN_INFO "=================================================\n"); |
@@ -265,7 +237,7 @@ static int __init tort_init(void) | |||
265 | if (!check_buf) | 237 | if (!check_buf) |
266 | goto out_patt_FF; | 238 | goto out_patt_FF; |
267 | 239 | ||
268 | bad_ebs = kcalloc(ebcnt, sizeof(*bad_ebs), GFP_KERNEL); | 240 | bad_ebs = kzalloc(ebcnt, GFP_KERNEL); |
269 | if (!bad_ebs) | 241 | if (!bad_ebs) |
270 | goto out_check_buf; | 242 | goto out_check_buf; |
271 | 243 | ||
@@ -283,40 +255,16 @@ static int __init tort_init(void) | |||
283 | } | 255 | } |
284 | } | 256 | } |
285 | 257 | ||
286 | /* | 258 | err = mtdtest_scan_for_bad_eraseblocks(mtd, bad_ebs, eb, ebcnt); |
287 | * Check if there is a bad eraseblock among those we are going to test. | 259 | if (err) |
288 | */ | 260 | goto out; |
289 | if (mtd_can_have_bb(mtd)) { | ||
290 | for (i = eb; i < eb + ebcnt; i++) { | ||
291 | err = mtd_block_isbad(mtd, (loff_t)i * mtd->erasesize); | ||
292 | |||
293 | if (err < 0) { | ||
294 | pr_info("block_isbad() returned %d " | ||
295 | "for EB %d\n", err, i); | ||
296 | goto out; | ||
297 | } | ||
298 | |||
299 | if (err) { | ||
300 | pr_err("EB %d is bad. Skip it.\n", i); | ||
301 | bad_ebs[i - eb] = 1; | ||
302 | } | ||
303 | } | ||
304 | } | ||
305 | 261 | ||
306 | start_timing(); | 262 | start_timing(); |
307 | while (1) { | 263 | while (1) { |
308 | int i; | 264 | int i; |
309 | void *patt; | 265 | void *patt; |
310 | 266 | ||
311 | /* Erase all eraseblocks */ | 267 | mtdtest_erase_good_eraseblocks(mtd, bad_ebs, eb, ebcnt); |
312 | for (i = eb; i < eb + ebcnt; i++) { | ||
313 | if (bad_ebs[i - eb]) | ||
314 | continue; | ||
315 | err = erase_eraseblock(i); | ||
316 | if (err) | ||
317 | goto out; | ||
318 | cond_resched(); | ||
319 | } | ||
320 | 268 | ||
321 | /* Check if the eraseblocks contain only 0xFF bytes */ | 269 | /* Check if the eraseblocks contain only 0xFF bytes */ |
322 | if (check) { | 270 | if (check) { |
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h index 211ff67e8b0d..95fc482cef36 100644 --- a/include/linux/mtd/bbm.h +++ b/include/linux/mtd/bbm.h | |||
@@ -93,8 +93,6 @@ struct nand_bbt_descr { | |||
93 | #define NAND_BBT_CREATE_EMPTY 0x00000400 | 93 | #define NAND_BBT_CREATE_EMPTY 0x00000400 |
94 | /* Search good / bad pattern through all pages of a block */ | 94 | /* Search good / bad pattern through all pages of a block */ |
95 | #define NAND_BBT_SCANALLPAGES 0x00000800 | 95 | #define NAND_BBT_SCANALLPAGES 0x00000800 |
96 | /* Scan block empty during good / bad block scan */ | ||
97 | #define NAND_BBT_SCANEMPTY 0x00001000 | ||
98 | /* Write bbt if neccecary */ | 96 | /* Write bbt if neccecary */ |
99 | #define NAND_BBT_WRITE 0x00002000 | 97 | #define NAND_BBT_WRITE 0x00002000 |
100 | /* Read and write back block contents when writing bbt */ | 98 | /* Read and write back block contents when writing bbt */ |
diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h index d6ed61ef451d..c8be32e9fc49 100644 --- a/include/linux/mtd/fsmc.h +++ b/include/linux/mtd/fsmc.h | |||
@@ -137,6 +137,7 @@ enum access_mode { | |||
137 | 137 | ||
138 | /** | 138 | /** |
139 | * fsmc_nand_platform_data - platform specific NAND controller config | 139 | * fsmc_nand_platform_data - platform specific NAND controller config |
140 | * @nand_timings: timing setup for the physical NAND interface | ||
140 | * @partitions: partition table for the platform, use a default fallback | 141 | * @partitions: partition table for the platform, use a default fallback |
141 | * if this is NULL | 142 | * if this is NULL |
142 | * @nr_partitions: the number of partitions in the previous entry | 143 | * @nr_partitions: the number of partitions in the previous entry |
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index a5cf4e8d6818..f9bfe526d310 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h | |||
@@ -173,6 +173,9 @@ struct mtd_info { | |||
173 | /* ECC layout structure pointer - read only! */ | 173 | /* ECC layout structure pointer - read only! */ |
174 | struct nand_ecclayout *ecclayout; | 174 | struct nand_ecclayout *ecclayout; |
175 | 175 | ||
176 | /* the ecc step size. */ | ||
177 | unsigned int ecc_step_size; | ||
178 | |||
176 | /* max number of correctible bit errors per ecc step */ | 179 | /* max number of correctible bit errors per ecc step */ |
177 | unsigned int ecc_strength; | 180 | unsigned int ecc_strength; |
178 | 181 | ||
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index ab6363443ce8..ac8e89d5a792 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h | |||
@@ -56,7 +56,7 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); | |||
56 | * is supported now. If you add a chip with bigger oobsize/page | 56 | * is supported now. If you add a chip with bigger oobsize/page |
57 | * adjust this accordingly. | 57 | * adjust this accordingly. |
58 | */ | 58 | */ |
59 | #define NAND_MAX_OOBSIZE 640 | 59 | #define NAND_MAX_OOBSIZE 744 |
60 | #define NAND_MAX_PAGESIZE 8192 | 60 | #define NAND_MAX_PAGESIZE 8192 |
61 | 61 | ||
62 | /* | 62 | /* |
@@ -202,6 +202,10 @@ typedef enum { | |||
202 | /* Keep gcc happy */ | 202 | /* Keep gcc happy */ |
203 | struct nand_chip; | 203 | struct nand_chip; |
204 | 204 | ||
205 | /* ONFI features */ | ||
206 | #define ONFI_FEATURE_16_BIT_BUS (1 << 0) | ||
207 | #define ONFI_FEATURE_EXT_PARAM_PAGE (1 << 7) | ||
208 | |||
205 | /* ONFI timing mode, used in both asynchronous and synchronous mode */ | 209 | /* ONFI timing mode, used in both asynchronous and synchronous mode */ |
206 | #define ONFI_TIMING_MODE_0 (1 << 0) | 210 | #define ONFI_TIMING_MODE_0 (1 << 0) |
207 | #define ONFI_TIMING_MODE_1 (1 << 1) | 211 | #define ONFI_TIMING_MODE_1 (1 << 1) |
@@ -217,6 +221,9 @@ struct nand_chip; | |||
217 | /* ONFI subfeature parameters length */ | 221 | /* ONFI subfeature parameters length */ |
218 | #define ONFI_SUBFEATURE_PARAM_LEN 4 | 222 | #define ONFI_SUBFEATURE_PARAM_LEN 4 |
219 | 223 | ||
224 | /* ONFI optional commands SET/GET FEATURES supported? */ | ||
225 | #define ONFI_OPT_CMD_SET_GET_FEATURES (1 << 2) | ||
226 | |||
220 | struct nand_onfi_params { | 227 | struct nand_onfi_params { |
221 | /* rev info and features block */ | 228 | /* rev info and features block */ |
222 | /* 'O' 'N' 'F' 'I' */ | 229 | /* 'O' 'N' 'F' 'I' */ |
@@ -224,7 +231,10 @@ struct nand_onfi_params { | |||
224 | __le16 revision; | 231 | __le16 revision; |
225 | __le16 features; | 232 | __le16 features; |
226 | __le16 opt_cmd; | 233 | __le16 opt_cmd; |
227 | u8 reserved[22]; | 234 | u8 reserved0[2]; |
235 | __le16 ext_param_page_length; /* since ONFI 2.1 */ | ||
236 | u8 num_of_param_pages; /* since ONFI 2.1 */ | ||
237 | u8 reserved1[17]; | ||
228 | 238 | ||
229 | /* manufacturer information block */ | 239 | /* manufacturer information block */ |
230 | char manufacturer[12]; | 240 | char manufacturer[12]; |
@@ -281,6 +291,40 @@ struct nand_onfi_params { | |||
281 | 291 | ||
282 | #define ONFI_CRC_BASE 0x4F4E | 292 | #define ONFI_CRC_BASE 0x4F4E |
283 | 293 | ||
294 | /* Extended ECC information Block Definition (since ONFI 2.1) */ | ||
295 | struct onfi_ext_ecc_info { | ||
296 | u8 ecc_bits; | ||
297 | u8 codeword_size; | ||
298 | __le16 bb_per_lun; | ||
299 | __le16 block_endurance; | ||
300 | u8 reserved[2]; | ||
301 | } __packed; | ||
302 | |||
303 | #define ONFI_SECTION_TYPE_0 0 /* Unused section. */ | ||
304 | #define ONFI_SECTION_TYPE_1 1 /* for additional sections. */ | ||
305 | #define ONFI_SECTION_TYPE_2 2 /* for ECC information. */ | ||
306 | struct onfi_ext_section { | ||
307 | u8 type; | ||
308 | u8 length; | ||
309 | } __packed; | ||
310 | |||
311 | #define ONFI_EXT_SECTION_MAX 8 | ||
312 | |||
313 | /* Extended Parameter Page Definition (since ONFI 2.1) */ | ||
314 | struct onfi_ext_param_page { | ||
315 | __le16 crc; | ||
316 | u8 sig[4]; /* 'E' 'P' 'P' 'S' */ | ||
317 | u8 reserved0[10]; | ||
318 | struct onfi_ext_section sections[ONFI_EXT_SECTION_MAX]; | ||
319 | |||
320 | /* | ||
321 | * The actual size of the Extended Parameter Page is in | ||
322 | * @ext_param_page_length of nand_onfi_params{}. | ||
323 | * The following are the variable length sections. | ||
324 | * So we do not add any fields below. Please see the ONFI spec. | ||
325 | */ | ||
326 | } __packed; | ||
327 | |||
284 | /** | 328 | /** |
285 | * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices | 329 | * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices |
286 | * @lock: protection lock | 330 | * @lock: protection lock |
@@ -390,8 +434,8 @@ struct nand_buffers { | |||
390 | * @write_buf: [REPLACEABLE] write data from the buffer to the chip | 434 | * @write_buf: [REPLACEABLE] write data from the buffer to the chip |
391 | * @read_buf: [REPLACEABLE] read data from the chip into the buffer | 435 | * @read_buf: [REPLACEABLE] read data from the chip into the buffer |
392 | * @select_chip: [REPLACEABLE] select chip nr | 436 | * @select_chip: [REPLACEABLE] select chip nr |
393 | * @block_bad: [REPLACEABLE] check, if the block is bad | 437 | * @block_bad: [REPLACEABLE] check if a block is bad, using OOB markers |
394 | * @block_markbad: [REPLACEABLE] mark the block bad | 438 | * @block_markbad: [REPLACEABLE] mark a block bad |
395 | * @cmd_ctrl: [BOARDSPECIFIC] hardwarespecific function for controlling | 439 | * @cmd_ctrl: [BOARDSPECIFIC] hardwarespecific function for controlling |
396 | * ALE/CLE/nCE. Also used to write command and address | 440 | * ALE/CLE/nCE. Also used to write command and address |
397 | * @init_size: [BOARDSPECIFIC] hardwarespecific function for setting | 441 | * @init_size: [BOARDSPECIFIC] hardwarespecific function for setting |
@@ -434,6 +478,12 @@ struct nand_buffers { | |||
434 | * bad block marker position; i.e., BBM == 11110111b is | 478 | * bad block marker position; i.e., BBM == 11110111b is |
435 | * not bad when badblockbits == 7 | 479 | * not bad when badblockbits == 7 |
436 | * @cellinfo: [INTERN] MLC/multichip data from chip ident | 480 | * @cellinfo: [INTERN] MLC/multichip data from chip ident |
481 | * @ecc_strength_ds: [INTERN] ECC correctability from the datasheet. | ||
482 | * Minimum amount of bit errors per @ecc_step_ds guaranteed | ||
483 | * to be correctable. If unknown, set to zero. | ||
484 | * @ecc_step_ds: [INTERN] ECC step required by the @ecc_strength_ds, | ||
485 | * also from the datasheet. It is the recommended ECC step | ||
486 | * size, if known; if unknown, set to zero. | ||
437 | * @numchips: [INTERN] number of physical chips | 487 | * @numchips: [INTERN] number of physical chips |
438 | * @chipsize: [INTERN] the size of one chip for multichip arrays | 488 | * @chipsize: [INTERN] the size of one chip for multichip arrays |
439 | * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1 | 489 | * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1 |
@@ -510,6 +560,8 @@ struct nand_chip { | |||
510 | unsigned int pagebuf_bitflips; | 560 | unsigned int pagebuf_bitflips; |
511 | int subpagesize; | 561 | int subpagesize; |
512 | uint8_t cellinfo; | 562 | uint8_t cellinfo; |
563 | uint16_t ecc_strength_ds; | ||
564 | uint16_t ecc_step_ds; | ||
513 | int badblockpos; | 565 | int badblockpos; |
514 | int badblockbits; | 566 | int badblockbits; |
515 | 567 | ||
@@ -576,6 +628,11 @@ struct nand_chip { | |||
576 | { .name = (nm), {{ .dev_id = (devid) }}, .chipsize = (chipsz), \ | 628 | { .name = (nm), {{ .dev_id = (devid) }}, .chipsize = (chipsz), \ |
577 | .options = (opts) } | 629 | .options = (opts) } |
578 | 630 | ||
631 | #define NAND_ECC_INFO(_strength, _step) \ | ||
632 | { .strength_ds = (_strength), .step_ds = (_step) } | ||
633 | #define NAND_ECC_STRENGTH(type) ((type)->ecc.strength_ds) | ||
634 | #define NAND_ECC_STEP(type) ((type)->ecc.step_ds) | ||
635 | |||
579 | /** | 636 | /** |
580 | * struct nand_flash_dev - NAND Flash Device ID Structure | 637 | * struct nand_flash_dev - NAND Flash Device ID Structure |
581 | * @name: a human-readable name of the NAND chip | 638 | * @name: a human-readable name of the NAND chip |
@@ -593,6 +650,12 @@ struct nand_chip { | |||
593 | * @options: stores various chip bit options | 650 | * @options: stores various chip bit options |
594 | * @id_len: The valid length of the @id. | 651 | * @id_len: The valid length of the @id. |
595 | * @oobsize: OOB size | 652 | * @oobsize: OOB size |
653 | * @ecc.strength_ds: The ECC correctability from the datasheet, same as the | ||
654 | * @ecc_strength_ds in nand_chip{}. | ||
655 | * @ecc.step_ds: The ECC step required by the @ecc.strength_ds, same as the | ||
656 | * @ecc_step_ds in nand_chip{}, also from the datasheet. | ||
657 | * For example, the "4bit ECC for each 512Byte" can be set with | ||
658 | * NAND_ECC_INFO(4, 512). | ||
596 | */ | 659 | */ |
597 | struct nand_flash_dev { | 660 | struct nand_flash_dev { |
598 | char *name; | 661 | char *name; |
@@ -609,6 +672,10 @@ struct nand_flash_dev { | |||
609 | unsigned int options; | 672 | unsigned int options; |
610 | uint16_t id_len; | 673 | uint16_t id_len; |
611 | uint16_t oobsize; | 674 | uint16_t oobsize; |
675 | struct { | ||
676 | uint16_t strength_ds; | ||
677 | uint16_t step_ds; | ||
678 | } ecc; | ||
612 | }; | 679 | }; |
613 | 680 | ||
614 | /** | 681 | /** |
@@ -625,8 +692,8 @@ extern struct nand_flash_dev nand_flash_ids[]; | |||
625 | extern struct nand_manufacturers nand_manuf_ids[]; | 692 | extern struct nand_manufacturers nand_manuf_ids[]; |
626 | 693 | ||
627 | extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd); | 694 | extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd); |
628 | extern int nand_update_bbt(struct mtd_info *mtd, loff_t offs); | ||
629 | extern int nand_default_bbt(struct mtd_info *mtd); | 695 | extern int nand_default_bbt(struct mtd_info *mtd); |
696 | extern int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs); | ||
630 | extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt); | 697 | extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt); |
631 | extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | 698 | extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, |
632 | int allowbbt); | 699 | int allowbbt); |
@@ -708,6 +775,12 @@ struct platform_nand_chip *get_platform_nandchip(struct mtd_info *mtd) | |||
708 | return chip->priv; | 775 | return chip->priv; |
709 | } | 776 | } |
710 | 777 | ||
778 | /* return the supported features. */ | ||
779 | static inline int onfi_feature(struct nand_chip *chip) | ||
780 | { | ||
781 | return chip->onfi_version ? le16_to_cpu(chip->onfi_params.features) : 0; | ||
782 | } | ||
783 | |||
711 | /* return the supported asynchronous timing mode. */ | 784 | /* return the supported asynchronous timing mode. */ |
712 | static inline int onfi_get_async_timing_mode(struct nand_chip *chip) | 785 | static inline int onfi_get_async_timing_mode(struct nand_chip *chip) |
713 | { | 786 | { |
diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h index 6a293b7fff3b..cea9f70133c5 100644 --- a/include/linux/platform_data/atmel.h +++ b/include/linux/platform_data/atmel.h | |||
@@ -71,6 +71,10 @@ struct atmel_nand_data { | |||
71 | u8 on_flash_bbt; /* bbt on flash */ | 71 | u8 on_flash_bbt; /* bbt on flash */ |
72 | struct mtd_partition *parts; | 72 | struct mtd_partition *parts; |
73 | unsigned int num_parts; | 73 | unsigned int num_parts; |
74 | bool has_dma; /* support dma transfer */ | ||
75 | |||
76 | /* default is false, only for at32ap7000 chip is true */ | ||
77 | bool need_reset_workaround; | ||
74 | }; | 78 | }; |
75 | 79 | ||
76 | /* Serial */ | 80 | /* Serial */ |
diff --git a/include/linux/platform_data/mtd-nand-pxa3xx.h b/include/linux/platform_data/mtd-nand-pxa3xx.h index c42f39f20195..ffb801998e5d 100644 --- a/include/linux/platform_data/mtd-nand-pxa3xx.h +++ b/include/linux/platform_data/mtd-nand-pxa3xx.h | |||
@@ -16,19 +16,6 @@ struct pxa3xx_nand_timing { | |||
16 | unsigned int tAR; /* ND_ALE low to ND_nRE low delay */ | 16 | unsigned int tAR; /* ND_ALE low to ND_nRE low delay */ |
17 | }; | 17 | }; |
18 | 18 | ||
19 | struct pxa3xx_nand_cmdset { | ||
20 | uint16_t read1; | ||
21 | uint16_t read2; | ||
22 | uint16_t program; | ||
23 | uint16_t read_status; | ||
24 | uint16_t read_id; | ||
25 | uint16_t erase; | ||
26 | uint16_t reset; | ||
27 | uint16_t lock; | ||
28 | uint16_t unlock; | ||
29 | uint16_t lock_status; | ||
30 | }; | ||
31 | |||
32 | struct pxa3xx_nand_flash { | 19 | struct pxa3xx_nand_flash { |
33 | char *name; | 20 | char *name; |
34 | uint32_t chip_id; | 21 | uint32_t chip_id; |