diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-23 20:38:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-23 20:38:39 -0400 |
commit | 54245ed870c8cf9ff87fdf78955ffbc93b261e9f (patch) | |
tree | d1cbb9294861c4f55d8d5fd6eac7b96f5283f538 | |
parent | 84e9c87e6ffc519fdf91949482a65672a7314c9a (diff) | |
parent | 0eb8618bd07533f423fed47399a0d6387bfe7cac (diff) |
Merge tag 'for-linus-20150623' of git://git.infradead.org/linux-mtd
Pull MTD updates from Brian Norris:
"JFFS2:
- fix a theoretical unbalanced locking issue; the lock handling was a
bit unclean, but AFAICT, it didn't actually lead to real deadlocks
NAND:
- brcmnand driver: new driver supporting NAND controller found
originally on Broadcom STB SoCs (BCM7xxx), but now also found on
BCM63xxx, iProc (e.g., Cygnus, BCM5301x), BCM3xxx, and more
- begin factoring out BBT code so it can be shared between
traditional (parallel) NAND drivers and upcoming SPI NAND drivers
(WIP)
- add common DT-based init support, so nand_base can pick up some
flash properties automatically, using established common NAND DT
properties
- mxc_nand: support 8-bit ECC
- pxa3xx_nand:
* fix build for ARM64
* use a jiffies-based timeout
SPI NOR:
- add a few new IDs
- clear out some unnecessary entries
- make sure SECT_4K flags are correct for all (?) entries
Core:
- fix mtd->usecount race conditions (BUG_ON())
- switch to modern PM ops
Other:
- CFI: save code space by de-inlining large functions
- clean up some partition parser selection code across several
drivers
- various miscellaneous changes, mostly minor"
* tag 'for-linus-20150623' of git://git.infradead.org/linux-mtd: (57 commits)
mtd: docg3: Fix kasprintf() usage
mtd: docg3: Don't leak docg3->bbt in error path
mtd: nandsim: Fix kasprintf() usage
mtd: cs553x_nand: Fix kasprintf() usage
mtd: r852: Fix device_create_file() usage
mtd: brcmnand: drop unnecessary initialization
mtd: propagate error codes from add_mtd_device()
mtd: diskonchip: remove two-phase partitioning / registration
mtd: dc21285: use raw spinlock functions for nw_gpio_lock
mtd: chips: fixup dependencies, to prevent build error
mtd: cfi_cmdset_0002: Initialize datum before calling map_word_load_partial
mtd: cfi: deinline large functions
mtd: lantiq-flash: use default partition parsers
mtd: plat_nand: use default partition probe
mtd: nand: correct indentation within conditional
mtd: remove incorrect file name
mtd: blktrans: use better error code for unimplemented ioctl()
mtd: maps: Spelling s/reseved/reserved/
mtd: blktrans: change blktrans_getgeo return value
mtd: mxc_nand: generate nand_ecclayout for 8 bit ECC
...
47 files changed, 3331 insertions, 396 deletions
diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt new file mode 100644 index 000000000000..4ff7128ee3b2 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt | |||
@@ -0,0 +1,150 @@ | |||
1 | * Broadcom STB NAND Controller | ||
2 | |||
3 | The Broadcom Set-Top Box NAND controller supports low-level access to raw NAND | ||
4 | flash chips. It has a memory-mapped register interface for both control | ||
5 | registers and for its data input/output buffer. On some SoCs, this controller is | ||
6 | paired with a custom DMA engine (inventively named "Flash DMA") which supports | ||
7 | basic PROGRAM and READ functions, among other features. | ||
8 | |||
9 | This controller was originally designed for STB SoCs (BCM7xxx) but is now | ||
10 | available on a variety of Broadcom SoCs, including some BCM3xxx, BCM63xx, and | ||
11 | iProc/Cygnus. Its history includes several similar (but not fully register | ||
12 | compatible) versions. | ||
13 | |||
14 | Required properties: | ||
15 | - compatible : May contain an SoC-specific compatibility string (see below) | ||
16 | to account for any SoC-specific hardware bits that may be | ||
17 | added on top of the base core controller. | ||
18 | In addition, must contain compatibility information about | ||
19 | the core NAND controller, of the following form: | ||
20 | "brcm,brcmnand" and an appropriate version compatibility | ||
21 | string, like "brcm,brcmnand-v7.0" | ||
22 | Possible values: | ||
23 | brcm,brcmnand-v4.0 | ||
24 | brcm,brcmnand-v5.0 | ||
25 | brcm,brcmnand-v6.0 | ||
26 | brcm,brcmnand-v6.1 | ||
27 | brcm,brcmnand-v7.0 | ||
28 | brcm,brcmnand-v7.1 | ||
29 | brcm,brcmnand | ||
30 | - reg : the register start and length for NAND register region. | ||
31 | (optional) Flash DMA register range (if present) | ||
32 | (optional) NAND flash cache range (if at non-standard offset) | ||
33 | - reg-names : a list of the names corresponding to the previous register | ||
34 | ranges. Should contain "nand" and (optionally) | ||
35 | "flash-dma" and/or "nand-cache". | ||
36 | - interrupts : The NAND CTLRDY interrupt and (if Flash DMA is available) | ||
37 | FLASH_DMA_DONE | ||
38 | - interrupt-names : May be "nand_ctlrdy" or "flash_dma_done", if broken out as | ||
39 | individual interrupts. | ||
40 | May be "nand", if the SoC has the individual NAND | ||
41 | interrupts multiplexed behind another custom piece of | ||
42 | hardware | ||
43 | - interrupt-parent : See standard interrupt bindings | ||
44 | - #address-cells : <1> - subnodes give the chip-select number | ||
45 | - #size-cells : <0> | ||
46 | |||
47 | Optional properties: | ||
48 | - brcm,nand-has-wp : Some versions of this IP include a write-protect | ||
49 | (WP) control bit. It is always available on >= | ||
50 | v7.0. Use this property to describe the rare | ||
51 | earlier versions of this core that include WP | ||
52 | |||
53 | -- Additonal SoC-specific NAND controller properties -- | ||
54 | |||
55 | The NAND controller is integrated differently on the variety of SoCs on which it | ||
56 | is found. Part of this integration involves providing status and enable bits | ||
57 | with which to control the 8 exposed NAND interrupts, as well as hardware for | ||
58 | configuring the endianness of the data bus. On some SoCs, these features are | ||
59 | handled via standard, modular components (e.g., their interrupts look like a | ||
60 | normal IRQ chip), but on others, they are controlled in unique and interesting | ||
61 | ways, sometimes with registers that lump multiple NAND-related functions | ||
62 | together. The former case can be described simply by the standard interrupts | ||
63 | properties in the main controller node. But for the latter exceptional cases, | ||
64 | we define additional 'compatible' properties and associated register resources within the NAND controller node above. | ||
65 | |||
66 | - compatible: Can be one of several SoC-specific strings. Each SoC may have | ||
67 | different requirements for its additional properties, as described below each | ||
68 | bullet point below. | ||
69 | |||
70 | * "brcm,nand-bcm63138" | ||
71 | - reg: (required) the 'NAND_INT_BASE' register range, with separate status | ||
72 | and enable registers | ||
73 | - reg-names: (required) "nand-int-base" | ||
74 | |||
75 | * "brcm,nand-iproc" | ||
76 | - reg: (required) the "IDM" register range, for interrupt enable and APB | ||
77 | bus access endianness configuration, and the "EXT" register range, | ||
78 | for interrupt status/ack. | ||
79 | - reg-names: (required) a list of the names corresponding to the previous | ||
80 | register ranges. Should contain "iproc-idm" and "iproc-ext". | ||
81 | |||
82 | |||
83 | * NAND chip-select | ||
84 | |||
85 | Each controller (compatible: "brcm,brcmnand") may contain one or more subnodes | ||
86 | to represent enabled chip-selects which (may) contain NAND flash chips. Their | ||
87 | properties are as follows. | ||
88 | |||
89 | Required properties: | ||
90 | - compatible : should contain "brcm,nandcs" | ||
91 | - reg : a single integer representing the chip-select | ||
92 | number (e.g., 0, 1, 2, etc.) | ||
93 | - #address-cells : see partition.txt | ||
94 | - #size-cells : see partition.txt | ||
95 | - nand-ecc-strength : see nand.txt | ||
96 | - nand-ecc-step-size : must be 512 or 1024. See nand.txt | ||
97 | |||
98 | Optional properties: | ||
99 | - nand-on-flash-bbt : boolean, to enable the on-flash BBT for this | ||
100 | chip-select. See nand.txt | ||
101 | - brcm,nand-oob-sector-size : integer, to denote the spare area sector size | ||
102 | expected for the ECC layout in use. This size, in | ||
103 | addition to the strength and step-size, | ||
104 | determines how the hardware BCH engine will lay | ||
105 | out the parity bytes it stores on the flash. | ||
106 | This property can be automatically determined by | ||
107 | the flash geometry (particularly the NAND page | ||
108 | and OOB size) in many cases, but when booting | ||
109 | from NAND, the boot controller has only a limited | ||
110 | number of available options for its default ECC | ||
111 | layout. | ||
112 | |||
113 | Each nandcs device node may optionally contain sub-nodes describing the flash | ||
114 | partition mapping. See partition.txt for more detail. | ||
115 | |||
116 | |||
117 | Example: | ||
118 | |||
119 | nand@f0442800 { | ||
120 | compatible = "brcm,brcmnand-v7.0", "brcm,brcmnand"; | ||
121 | reg = <0xF0442800 0x600>, | ||
122 | <0xF0443000 0x100>; | ||
123 | reg-names = "nand", "flash-dma"; | ||
124 | interrupt-parent = <&hif_intr2_intc>; | ||
125 | interrupts = <24>, <4>; | ||
126 | |||
127 | #address-cells = <1>; | ||
128 | #size-cells = <0>; | ||
129 | |||
130 | nandcs@1 { | ||
131 | compatible = "brcm,nandcs"; | ||
132 | reg = <1>; // Chip select 1 | ||
133 | nand-on-flash-bbt; | ||
134 | nand-ecc-strength = <12>; | ||
135 | nand-ecc-step-size = <512>; | ||
136 | |||
137 | // Partitions | ||
138 | #address-cells = <1>; // <2>, for 64-bit offset | ||
139 | #size-cells = <1>; // <2>, for 64-bit length | ||
140 | flash0.rootfs@0 { | ||
141 | reg = <0 0x10000000>; | ||
142 | }; | ||
143 | flash0@0 { | ||
144 | reg = <0 0>; // MTDPART_SIZ_FULL | ||
145 | }; | ||
146 | flash0.kernel@10000000 { | ||
147 | reg = <0x10000000 0x400000>; | ||
148 | }; | ||
149 | }; | ||
150 | }; | ||
diff --git a/MAINTAINERS b/MAINTAINERS index a0ee3ca890ed..e46cf6f0e5b0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -2267,6 +2267,12 @@ S: Supported | |||
2267 | F: drivers/gpio/gpio-bcm-kona.c | 2267 | F: drivers/gpio/gpio-bcm-kona.c |
2268 | F: Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt | 2268 | F: Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt |
2269 | 2269 | ||
2270 | BROADCOM STB NAND FLASH DRIVER | ||
2271 | M: Brian Norris <computersforpeace@gmail.com> | ||
2272 | L: linux-mtd@lists.infradead.org | ||
2273 | S: Maintained | ||
2274 | F: drivers/mtd/nand/brcmnand/ | ||
2275 | |||
2270 | BROADCOM SPECIFIC AMBA DRIVER (BCMA) | 2276 | BROADCOM SPECIFIC AMBA DRIVER (BCMA) |
2271 | M: Rafał Miłecki <zajec5@gmail.com> | 2277 | M: Rafał Miłecki <zajec5@gmail.com> |
2272 | L: linux-wireless@vger.kernel.org | 2278 | L: linux-wireless@vger.kernel.org |
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig index 9f02c28c0204..54479c481a7a 100644 --- a/drivers/mtd/chips/Kconfig +++ b/drivers/mtd/chips/Kconfig | |||
@@ -16,6 +16,7 @@ config MTD_CFI | |||
16 | config MTD_JEDECPROBE | 16 | config MTD_JEDECPROBE |
17 | tristate "Detect non-CFI AMD/JEDEC-compatible flash chips" | 17 | tristate "Detect non-CFI AMD/JEDEC-compatible flash chips" |
18 | select MTD_GEN_PROBE | 18 | select MTD_GEN_PROBE |
19 | select MTD_CFI_UTIL | ||
19 | help | 20 | help |
20 | This option enables JEDEC-style probing of flash chips which are not | 21 | This option enables JEDEC-style probing of flash chips which are not |
21 | compatible with the Common Flash Interface, but will use the common | 22 | compatible with the Common Flash Interface, but will use the common |
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index c50d8cf0f60d..c3624eb571d1 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
@@ -1295,7 +1295,7 @@ static int do_otp_write(struct map_info *map, struct flchip *chip, loff_t adr, | |||
1295 | unsigned long bus_ofs = adr & ~(map_bankwidth(map)-1); | 1295 | unsigned long bus_ofs = adr & ~(map_bankwidth(map)-1); |
1296 | int gap = adr - bus_ofs; | 1296 | int gap = adr - bus_ofs; |
1297 | int n = min_t(int, len, map_bankwidth(map) - gap); | 1297 | int n = min_t(int, len, map_bankwidth(map) - gap); |
1298 | map_word datum; | 1298 | map_word datum = map_word_ff(map); |
1299 | 1299 | ||
1300 | if (n != map_bankwidth(map)) { | 1300 | if (n != map_bankwidth(map)) { |
1301 | /* partial write of a word, load old contents */ | 1301 | /* partial write of a word, load old contents */ |
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c index 09c79bd0b4f4..6f16552cd59f 100644 --- a/drivers/mtd/chips/cfi_util.c +++ b/drivers/mtd/chips/cfi_util.c | |||
@@ -23,6 +23,194 @@ | |||
23 | #include <linux/mtd/map.h> | 23 | #include <linux/mtd/map.h> |
24 | #include <linux/mtd/cfi.h> | 24 | #include <linux/mtd/cfi.h> |
25 | 25 | ||
26 | void cfi_udelay(int us) | ||
27 | { | ||
28 | if (us >= 1000) { | ||
29 | msleep((us+999)/1000); | ||
30 | } else { | ||
31 | udelay(us); | ||
32 | cond_resched(); | ||
33 | } | ||
34 | } | ||
35 | EXPORT_SYMBOL(cfi_udelay); | ||
36 | |||
37 | /* | ||
38 | * Returns the command address according to the given geometry. | ||
39 | */ | ||
40 | uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, | ||
41 | struct map_info *map, struct cfi_private *cfi) | ||
42 | { | ||
43 | unsigned bankwidth = map_bankwidth(map); | ||
44 | unsigned interleave = cfi_interleave(cfi); | ||
45 | unsigned type = cfi->device_type; | ||
46 | uint32_t addr; | ||
47 | |||
48 | addr = (cmd_ofs * type) * interleave; | ||
49 | |||
50 | /* Modify the unlock address if we are in compatibility mode. | ||
51 | * For 16bit devices on 8 bit busses | ||
52 | * and 32bit devices on 16 bit busses | ||
53 | * set the low bit of the alternating bit sequence of the address. | ||
54 | */ | ||
55 | if (((type * interleave) > bankwidth) && ((cmd_ofs & 0xff) == 0xaa)) | ||
56 | addr |= (type >> 1)*interleave; | ||
57 | |||
58 | return addr; | ||
59 | } | ||
60 | EXPORT_SYMBOL(cfi_build_cmd_addr); | ||
61 | |||
62 | /* | ||
63 | * Transforms the CFI command for the given geometry (bus width & interleave). | ||
64 | * It looks too long to be inline, but in the common case it should almost all | ||
65 | * get optimised away. | ||
66 | */ | ||
67 | map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cfi_private *cfi) | ||
68 | { | ||
69 | map_word val = { {0} }; | ||
70 | int wordwidth, words_per_bus, chip_mode, chips_per_word; | ||
71 | unsigned long onecmd; | ||
72 | int i; | ||
73 | |||
74 | /* We do it this way to give the compiler a fighting chance | ||
75 | of optimising away all the crap for 'bankwidth' larger than | ||
76 | an unsigned long, in the common case where that support is | ||
77 | disabled */ | ||
78 | if (map_bankwidth_is_large(map)) { | ||
79 | wordwidth = sizeof(unsigned long); | ||
80 | words_per_bus = (map_bankwidth(map)) / wordwidth; // i.e. normally 1 | ||
81 | } else { | ||
82 | wordwidth = map_bankwidth(map); | ||
83 | words_per_bus = 1; | ||
84 | } | ||
85 | |||
86 | chip_mode = map_bankwidth(map) / cfi_interleave(cfi); | ||
87 | chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map); | ||
88 | |||
89 | /* First, determine what the bit-pattern should be for a single | ||
90 | device, according to chip mode and endianness... */ | ||
91 | switch (chip_mode) { | ||
92 | default: BUG(); | ||
93 | case 1: | ||
94 | onecmd = cmd; | ||
95 | break; | ||
96 | case 2: | ||
97 | onecmd = cpu_to_cfi16(map, cmd); | ||
98 | break; | ||
99 | case 4: | ||
100 | onecmd = cpu_to_cfi32(map, cmd); | ||
101 | break; | ||
102 | } | ||
103 | |||
104 | /* Now replicate it across the size of an unsigned long, or | ||
105 | just to the bus width as appropriate */ | ||
106 | switch (chips_per_word) { | ||
107 | default: BUG(); | ||
108 | #if BITS_PER_LONG >= 64 | ||
109 | case 8: | ||
110 | onecmd |= (onecmd << (chip_mode * 32)); | ||
111 | #endif | ||
112 | case 4: | ||
113 | onecmd |= (onecmd << (chip_mode * 16)); | ||
114 | case 2: | ||
115 | onecmd |= (onecmd << (chip_mode * 8)); | ||
116 | case 1: | ||
117 | ; | ||
118 | } | ||
119 | |||
120 | /* And finally, for the multi-word case, replicate it | ||
121 | in all words in the structure */ | ||
122 | for (i=0; i < words_per_bus; i++) { | ||
123 | val.x[i] = onecmd; | ||
124 | } | ||
125 | |||
126 | return val; | ||
127 | } | ||
128 | EXPORT_SYMBOL(cfi_build_cmd); | ||
129 | |||
130 | unsigned long cfi_merge_status(map_word val, struct map_info *map, | ||
131 | struct cfi_private *cfi) | ||
132 | { | ||
133 | int wordwidth, words_per_bus, chip_mode, chips_per_word; | ||
134 | unsigned long onestat, res = 0; | ||
135 | int i; | ||
136 | |||
137 | /* We do it this way to give the compiler a fighting chance | ||
138 | of optimising away all the crap for 'bankwidth' larger than | ||
139 | an unsigned long, in the common case where that support is | ||
140 | disabled */ | ||
141 | if (map_bankwidth_is_large(map)) { | ||
142 | wordwidth = sizeof(unsigned long); | ||
143 | words_per_bus = (map_bankwidth(map)) / wordwidth; // i.e. normally 1 | ||
144 | } else { | ||
145 | wordwidth = map_bankwidth(map); | ||
146 | words_per_bus = 1; | ||
147 | } | ||
148 | |||
149 | chip_mode = map_bankwidth(map) / cfi_interleave(cfi); | ||
150 | chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map); | ||
151 | |||
152 | onestat = val.x[0]; | ||
153 | /* Or all status words together */ | ||
154 | for (i=1; i < words_per_bus; i++) { | ||
155 | onestat |= val.x[i]; | ||
156 | } | ||
157 | |||
158 | res = onestat; | ||
159 | switch(chips_per_word) { | ||
160 | default: BUG(); | ||
161 | #if BITS_PER_LONG >= 64 | ||
162 | case 8: | ||
163 | res |= (onestat >> (chip_mode * 32)); | ||
164 | #endif | ||
165 | case 4: | ||
166 | res |= (onestat >> (chip_mode * 16)); | ||
167 | case 2: | ||
168 | res |= (onestat >> (chip_mode * 8)); | ||
169 | case 1: | ||
170 | ; | ||
171 | } | ||
172 | |||
173 | /* Last, determine what the bit-pattern should be for a single | ||
174 | device, according to chip mode and endianness... */ | ||
175 | switch (chip_mode) { | ||
176 | case 1: | ||
177 | break; | ||
178 | case 2: | ||
179 | res = cfi16_to_cpu(map, res); | ||
180 | break; | ||
181 | case 4: | ||
182 | res = cfi32_to_cpu(map, res); | ||
183 | break; | ||
184 | default: BUG(); | ||
185 | } | ||
186 | return res; | ||
187 | } | ||
188 | EXPORT_SYMBOL(cfi_merge_status); | ||
189 | |||
190 | /* | ||
191 | * Sends a CFI command to a bank of flash for the given geometry. | ||
192 | * | ||
193 | * Returns the offset in flash where the command was written. | ||
194 | * If prev_val is non-null, it will be set to the value at the command address, | ||
195 | * before the command was written. | ||
196 | */ | ||
197 | uint32_t cfi_send_gen_cmd(u_char cmd, uint32_t cmd_addr, uint32_t base, | ||
198 | struct map_info *map, struct cfi_private *cfi, | ||
199 | int type, map_word *prev_val) | ||
200 | { | ||
201 | map_word val; | ||
202 | uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, map, cfi); | ||
203 | val = cfi_build_cmd(cmd, map, cfi); | ||
204 | |||
205 | if (prev_val) | ||
206 | *prev_val = map_read(map, addr); | ||
207 | |||
208 | map_write(map, val, addr); | ||
209 | |||
210 | return addr - base; | ||
211 | } | ||
212 | EXPORT_SYMBOL(cfi_send_gen_cmd); | ||
213 | |||
26 | int __xipram cfi_qry_present(struct map_info *map, __u32 base, | 214 | int __xipram cfi_qry_present(struct map_info *map, __u32 base, |
27 | struct cfi_private *cfi) | 215 | struct cfi_private *cfi) |
28 | { | 216 | { |
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index 866d31904475..5e67b4acde78 100644 --- a/drivers/mtd/devices/docg3.c +++ b/drivers/mtd/devices/docg3.c | |||
@@ -1815,7 +1815,7 @@ static void doc_dbg_unregister(struct docg3 *docg3) | |||
1815 | * @chip_id: The chip ID of the supported chip | 1815 | * @chip_id: The chip ID of the supported chip |
1816 | * @mtd: The structure to fill | 1816 | * @mtd: The structure to fill |
1817 | */ | 1817 | */ |
1818 | static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) | 1818 | static int __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) |
1819 | { | 1819 | { |
1820 | struct docg3 *docg3 = mtd->priv; | 1820 | struct docg3 *docg3 = mtd->priv; |
1821 | int cfg; | 1821 | int cfg; |
@@ -1828,6 +1828,8 @@ static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) | |||
1828 | case DOC_CHIPID_G3: | 1828 | case DOC_CHIPID_G3: |
1829 | mtd->name = kasprintf(GFP_KERNEL, "docg3.%d", | 1829 | mtd->name = kasprintf(GFP_KERNEL, "docg3.%d", |
1830 | docg3->device_id); | 1830 | docg3->device_id); |
1831 | if (!mtd->name) | ||
1832 | return -ENOMEM; | ||
1831 | docg3->max_block = 2047; | 1833 | docg3->max_block = 2047; |
1832 | break; | 1834 | break; |
1833 | } | 1835 | } |
@@ -1850,6 +1852,8 @@ static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd) | |||
1850 | mtd->_block_isbad = doc_block_isbad; | 1852 | mtd->_block_isbad = doc_block_isbad; |
1851 | mtd->ecclayout = &docg3_oobinfo; | 1853 | mtd->ecclayout = &docg3_oobinfo; |
1852 | mtd->ecc_strength = DOC_ECC_BCH_T; | 1854 | mtd->ecc_strength = DOC_ECC_BCH_T; |
1855 | |||
1856 | return 0; | ||
1853 | } | 1857 | } |
1854 | 1858 | ||
1855 | /** | 1859 | /** |
@@ -1900,7 +1904,7 @@ doc_probe_device(struct docg3_cascade *cascade, int floor, struct device *dev) | |||
1900 | 1904 | ||
1901 | ret = 0; | 1905 | ret = 0; |
1902 | if (chip_id != (u16)(~chip_id_inv)) { | 1906 | if (chip_id != (u16)(~chip_id_inv)) { |
1903 | goto nomem3; | 1907 | goto nomem4; |
1904 | } | 1908 | } |
1905 | 1909 | ||
1906 | switch (chip_id) { | 1910 | switch (chip_id) { |
@@ -1910,15 +1914,19 @@ doc_probe_device(struct docg3_cascade *cascade, int floor, struct device *dev) | |||
1910 | break; | 1914 | break; |
1911 | default: | 1915 | default: |
1912 | doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id); | 1916 | doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id); |
1913 | goto nomem3; | 1917 | goto nomem4; |
1914 | } | 1918 | } |
1915 | 1919 | ||
1916 | doc_set_driver_info(chip_id, mtd); | 1920 | ret = doc_set_driver_info(chip_id, mtd); |
1921 | if (ret) | ||
1922 | goto nomem4; | ||
1917 | 1923 | ||
1918 | doc_hamming_ecc_init(docg3, DOC_LAYOUT_OOB_PAGEINFO_SZ); | 1924 | doc_hamming_ecc_init(docg3, DOC_LAYOUT_OOB_PAGEINFO_SZ); |
1919 | doc_reload_bbt(docg3); | 1925 | doc_reload_bbt(docg3); |
1920 | return mtd; | 1926 | return mtd; |
1921 | 1927 | ||
1928 | nomem4: | ||
1929 | kfree(docg3->bbt); | ||
1922 | nomem3: | 1930 | nomem3: |
1923 | kfree(mtd); | 1931 | kfree(mtd); |
1924 | nomem2: | 1932 | nomem2: |
@@ -2117,7 +2125,7 @@ static int docg3_release(struct platform_device *pdev) | |||
2117 | } | 2125 | } |
2118 | 2126 | ||
2119 | #ifdef CONFIG_OF | 2127 | #ifdef CONFIG_OF |
2120 | static struct of_device_id docg3_dt_ids[] = { | 2128 | static const struct of_device_id docg3_dt_ids[] = { |
2121 | { .compatible = "m-systems,diskonchip-g3" }, | 2129 | { .compatible = "m-systems,diskonchip-g3" }, |
2122 | {} | 2130 | {} |
2123 | }; | 2131 | }; |
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 3af137f49ac9..d313f948b96c 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -261,45 +261,33 @@ static int m25p_remove(struct spi_device *spi) | |||
261 | * keep them available as module aliases for existing platforms. | 261 | * keep them available as module aliases for existing platforms. |
262 | */ | 262 | */ |
263 | static const struct spi_device_id m25p_ids[] = { | 263 | static const struct spi_device_id m25p_ids[] = { |
264 | {"at25fs010"}, {"at25fs040"}, {"at25df041a"}, {"at25df321a"}, | 264 | /* |
265 | {"at25df641"}, {"at26f004"}, {"at26df081a"}, {"at26df161a"}, | 265 | * Entries not used in DTs that should be safe to drop after replacing |
266 | {"at26df321"}, {"at45db081d"}, | 266 | * them with "nor-jedec" in platform data. |
267 | {"en25f32"}, {"en25p32"}, {"en25q32b"}, {"en25p64"}, | 267 | */ |
268 | {"en25q64"}, {"en25qh128"}, {"en25qh256"}, | 268 | {"s25sl064a"}, {"w25x16"}, {"m25p10"}, {"m25px64"}, |
269 | {"f25l32pa"}, | 269 | |
270 | {"mr25h256"}, {"mr25h10"}, | 270 | /* |
271 | {"gd25q32"}, {"gd25q64"}, | 271 | * Entries that were used in DTs without "nor-jedec" fallback and should |
272 | {"160s33b"}, {"320s33b"}, {"640s33b"}, | 272 | * be kept for backward compatibility. |
273 | {"mx25l2005a"}, {"mx25l4005a"}, {"mx25l8005"}, {"mx25l1606e"}, | 273 | */ |
274 | {"mx25l3205d"}, {"mx25l3255e"}, {"mx25l6405d"}, {"mx25l12805d"}, | 274 | {"at25df321a"}, {"at25df641"}, {"at26df081a"}, |
275 | {"mx25l12855e"},{"mx25l25635e"},{"mx25l25655e"},{"mx66l51235l"}, | 275 | {"mr25h256"}, |
276 | {"mx66l1g55g"}, | 276 | {"mx25l4005a"}, {"mx25l1606e"}, {"mx25l6405d"}, {"mx25l12805d"}, |
277 | {"n25q064"}, {"n25q128a11"}, {"n25q128a13"}, {"n25q256a"}, | 277 | {"mx25l25635e"},{"mx66l51235l"}, |
278 | {"n25q512a"}, {"n25q512ax3"}, {"n25q00"}, | 278 | {"n25q064"}, {"n25q128a11"}, {"n25q128a13"}, {"n25q512a"}, |
279 | {"pm25lv512"}, {"pm25lv010"}, {"pm25lq032"}, | 279 | {"s25fl256s1"}, {"s25fl512s"}, {"s25sl12801"}, {"s25fl008k"}, |
280 | {"s25sl032p"}, {"s25sl064p"}, {"s25fl256s0"}, {"s25fl256s1"}, | 280 | {"s25fl064k"}, |
281 | {"s25fl512s"}, {"s70fl01gs"}, {"s25sl12800"}, {"s25sl12801"}, | 281 | {"sst25vf040b"},{"sst25vf016b"},{"sst25vf032b"},{"sst25wf040"}, |
282 | {"s25fl129p0"}, {"s25fl129p1"}, {"s25sl004a"}, {"s25sl008a"}, | 282 | {"m25p40"}, {"m25p80"}, {"m25p16"}, {"m25p32"}, |
283 | {"s25sl016a"}, {"s25sl032a"}, {"s25sl064a"}, {"s25fl008k"}, | 283 | {"m25p64"}, {"m25p128"}, |
284 | {"s25fl016k"}, {"s25fl064k"}, {"s25fl132k"}, | 284 | {"w25x80"}, {"w25x32"}, {"w25q32"}, {"w25q32dw"}, |
285 | {"sst25vf040b"},{"sst25vf080b"},{"sst25vf016b"},{"sst25vf032b"}, | 285 | {"w25q80bl"}, {"w25q128"}, {"w25q256"}, |
286 | {"sst25vf064c"},{"sst25wf512"}, {"sst25wf010"}, {"sst25wf020"}, | 286 | |
287 | {"sst25wf040"}, | 287 | /* Flashes that can't be detected using JEDEC */ |
288 | {"m25p05"}, {"m25p10"}, {"m25p20"}, {"m25p40"}, | ||
289 | {"m25p80"}, {"m25p16"}, {"m25p32"}, {"m25p64"}, | ||
290 | {"m25p128"}, {"n25q032"}, | ||
291 | {"m25p05-nonjedec"}, {"m25p10-nonjedec"}, {"m25p20-nonjedec"}, | 288 | {"m25p05-nonjedec"}, {"m25p10-nonjedec"}, {"m25p20-nonjedec"}, |
292 | {"m25p40-nonjedec"}, {"m25p80-nonjedec"}, {"m25p16-nonjedec"}, | 289 | {"m25p40-nonjedec"}, {"m25p80-nonjedec"}, {"m25p16-nonjedec"}, |
293 | {"m25p32-nonjedec"}, {"m25p64-nonjedec"}, {"m25p128-nonjedec"}, | 290 | {"m25p32-nonjedec"}, {"m25p64-nonjedec"}, {"m25p128-nonjedec"}, |
294 | {"m45pe10"}, {"m45pe80"}, {"m45pe16"}, | ||
295 | {"m25pe20"}, {"m25pe80"}, {"m25pe16"}, | ||
296 | {"m25px16"}, {"m25px32"}, {"m25px32-s0"}, {"m25px32-s1"}, | ||
297 | {"m25px64"}, {"m25px80"}, | ||
298 | {"w25x10"}, {"w25x20"}, {"w25x40"}, {"w25x80"}, | ||
299 | {"w25x16"}, {"w25x32"}, {"w25q32"}, {"w25q32dw"}, | ||
300 | {"w25x64"}, {"w25q64"}, {"w25q80"}, {"w25q80bl"}, | ||
301 | {"w25q128"}, {"w25q256"}, {"cat25c11"}, | ||
302 | {"cat25c03"}, {"cat25c09"}, {"cat25c17"}, {"cat25128"}, | ||
303 | 291 | ||
304 | /* | 292 | /* |
305 | * Generic support for SPI NOR that can be identified by the JEDEC READ | 293 | * Generic support for SPI NOR that can be identified by the JEDEC READ |
diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c index 508bab3bd0c4..04b24d2b03f2 100644 --- a/drivers/mtd/devices/spear_smi.c +++ b/drivers/mtd/devices/spear_smi.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * SMI (Serial Memory Controller) device driver for Serial NOR Flash on | 2 | * SMI (Serial Memory Controller) device driver for Serial NOR Flash on |
3 | * SPEAr platform | 3 | * SPEAr platform |
4 | * The serial nor interface is largely based on drivers/mtd/m25p80.c, | 4 | * The serial nor interface is largely based on m25p80.c, however the SPI |
5 | * however the SPI interface has been replaced by SMI. | 5 | * interface has been replaced by SMI. |
6 | * | 6 | * |
7 | * Copyright © 2010 STMicroelectronics. | 7 | * Copyright © 2010 STMicroelectronics. |
8 | * Ashish Priyadarshi | 8 | * Ashish Priyadarshi |
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index e715ae90632f..7c95a656f9e4 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
@@ -326,7 +326,7 @@ config MTD_BFIN_ASYNC | |||
326 | 326 | ||
327 | config MTD_GPIO_ADDR | 327 | config MTD_GPIO_ADDR |
328 | tristate "GPIO-assisted Flash Chip Support" | 328 | tristate "GPIO-assisted Flash Chip Support" |
329 | depends on GPIOLIB | 329 | depends on GPIOLIB || COMPILE_TEST |
330 | depends on MTD_COMPLEX_MAPPINGS | 330 | depends on MTD_COMPLEX_MAPPINGS |
331 | help | 331 | help |
332 | Map driver which allows flashes to be partially physically addressed | 332 | Map driver which allows flashes to be partially physically addressed |
diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c index f7207b0a76dc..f2b68667ea59 100644 --- a/drivers/mtd/maps/amd76xrom.c +++ b/drivers/mtd/maps/amd76xrom.c | |||
@@ -138,7 +138,7 @@ static int amd76xrom_init_one(struct pci_dev *pdev, | |||
138 | /* | 138 | /* |
139 | * Try to reserve the window mem region. If this fails then | 139 | * Try to reserve the window mem region. If this fails then |
140 | * it is likely due to a fragment of the window being | 140 | * it is likely due to a fragment of the window being |
141 | * "reseved" by the BIOS. In the case that the | 141 | * "reserved" by the BIOS. In the case that the |
142 | * request_mem_region() fails then once the rom size is | 142 | * request_mem_region() fails then once the rom size is |
143 | * discovered we will try to reserve the unreserved fragment. | 143 | * discovered we will try to reserve the unreserved fragment. |
144 | */ | 144 | */ |
diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c index f8a7dd14cee0..70a3db3ab856 100644 --- a/drivers/mtd/maps/dc21285.c +++ b/drivers/mtd/maps/dc21285.c | |||
@@ -38,9 +38,9 @@ static void nw_en_write(void) | |||
38 | * we want to write a bit pattern XXX1 to Xilinx to enable | 38 | * we want to write a bit pattern XXX1 to Xilinx to enable |
39 | * the write gate, which will be open for about the next 2ms. | 39 | * the write gate, which will be open for about the next 2ms. |
40 | */ | 40 | */ |
41 | spin_lock_irqsave(&nw_gpio_lock, flags); | 41 | raw_spin_lock_irqsave(&nw_gpio_lock, flags); |
42 | nw_cpld_modify(CPLD_FLASH_WR_ENABLE, CPLD_FLASH_WR_ENABLE); | 42 | nw_cpld_modify(CPLD_FLASH_WR_ENABLE, CPLD_FLASH_WR_ENABLE); |
43 | spin_unlock_irqrestore(&nw_gpio_lock, flags); | 43 | raw_spin_unlock_irqrestore(&nw_gpio_lock, flags); |
44 | 44 | ||
45 | /* | 45 | /* |
46 | * let the ISA bus to catch on... | 46 | * let the ISA bus to catch on... |
diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c index f784cf0caa13..76ed651b515b 100644 --- a/drivers/mtd/maps/esb2rom.c +++ b/drivers/mtd/maps/esb2rom.c | |||
@@ -234,7 +234,7 @@ static int esb2rom_init_one(struct pci_dev *pdev, | |||
234 | 234 | ||
235 | /* | 235 | /* |
236 | * Try to reserve the window mem region. If this fails then | 236 | * Try to reserve the window mem region. If this fails then |
237 | * it is likely due to the window being "reseved" by the BIOS. | 237 | * it is likely due to the window being "reserved" by the BIOS. |
238 | */ | 238 | */ |
239 | window->rsrc.name = MOD_NAME; | 239 | window->rsrc.name = MOD_NAME; |
240 | window->rsrc.start = window->phys; | 240 | window->rsrc.start = window->phys; |
diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c index c7478e18f485..8636bba42200 100644 --- a/drivers/mtd/maps/ichxrom.c +++ b/drivers/mtd/maps/ichxrom.c | |||
@@ -167,7 +167,7 @@ static int ichxrom_init_one(struct pci_dev *pdev, | |||
167 | 167 | ||
168 | /* | 168 | /* |
169 | * Try to reserve the window mem region. If this fails then | 169 | * Try to reserve the window mem region. If this fails then |
170 | * it is likely due to the window being "reseved" by the BIOS. | 170 | * it is likely due to the window being "reserved" by the BIOS. |
171 | */ | 171 | */ |
172 | window->rsrc.name = MOD_NAME; | 172 | window->rsrc.name = MOD_NAME; |
173 | window->rsrc.start = window->phys; | 173 | window->rsrc.start = window->phys; |
diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c index 33d26f5bee54..e2f878216048 100644 --- a/drivers/mtd/maps/lantiq-flash.c +++ b/drivers/mtd/maps/lantiq-flash.c | |||
@@ -45,7 +45,6 @@ struct ltq_mtd { | |||
45 | }; | 45 | }; |
46 | 46 | ||
47 | static const char ltq_map_name[] = "ltq_nor"; | 47 | static const char ltq_map_name[] = "ltq_nor"; |
48 | static const char * const ltq_probe_types[] = { "cmdlinepart", "ofpart", NULL }; | ||
49 | 48 | ||
50 | static map_word | 49 | static map_word |
51 | ltq_read16(struct map_info *map, unsigned long adr) | 50 | ltq_read16(struct map_info *map, unsigned long adr) |
@@ -168,8 +167,7 @@ ltq_mtd_probe(struct platform_device *pdev) | |||
168 | cfi->addr_unlock2 ^= 1; | 167 | cfi->addr_unlock2 ^= 1; |
169 | 168 | ||
170 | ppdata.of_node = pdev->dev.of_node; | 169 | ppdata.of_node = pdev->dev.of_node; |
171 | err = mtd_device_parse_register(ltq_mtd->mtd, ltq_probe_types, | 170 | err = mtd_device_parse_register(ltq_mtd->mtd, NULL, &ppdata, NULL, 0); |
172 | &ppdata, NULL, 0); | ||
173 | if (err) { | 171 | if (err) { |
174 | dev_err(&pdev->dev, "failed to add partitions\n"); | 172 | dev_err(&pdev->dev, "failed to add partitions\n"); |
175 | goto err_destroy; | 173 | goto err_destroy; |
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index ff26e979b1a1..774b32fd29e6 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c | |||
@@ -147,7 +147,7 @@ static void of_free_probes(const char * const *probes) | |||
147 | kfree(probes); | 147 | kfree(probes); |
148 | } | 148 | } |
149 | 149 | ||
150 | static struct of_device_id of_flash_match[]; | 150 | static const struct of_device_id of_flash_match[]; |
151 | static int of_flash_probe(struct platform_device *dev) | 151 | static int of_flash_probe(struct platform_device *dev) |
152 | { | 152 | { |
153 | const char * const *part_probe_types; | 153 | const char * const *part_probe_types; |
@@ -327,7 +327,7 @@ err_flash_remove: | |||
327 | return err; | 327 | return err; |
328 | } | 328 | } |
329 | 329 | ||
330 | static struct of_device_id of_flash_match[] = { | 330 | static const struct of_device_id of_flash_match[] = { |
331 | { | 331 | { |
332 | .compatible = "cfi-flash", | 332 | .compatible = "cfi-flash", |
333 | .data = (void *)"cfi_probe", | 333 | .data = (void *)"cfi_probe", |
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 2b0c52870999..41acc507b22e 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c | |||
@@ -197,6 +197,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode) | |||
197 | return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/ | 197 | return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/ |
198 | 198 | ||
199 | mutex_lock(&dev->lock); | 199 | mutex_lock(&dev->lock); |
200 | mutex_lock(&mtd_table_mutex); | ||
200 | 201 | ||
201 | if (dev->open) | 202 | if (dev->open) |
202 | goto unlock; | 203 | goto unlock; |
@@ -220,6 +221,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode) | |||
220 | 221 | ||
221 | unlock: | 222 | unlock: |
222 | dev->open++; | 223 | dev->open++; |
224 | mutex_unlock(&mtd_table_mutex); | ||
223 | mutex_unlock(&dev->lock); | 225 | mutex_unlock(&dev->lock); |
224 | blktrans_dev_put(dev); | 226 | blktrans_dev_put(dev); |
225 | return ret; | 227 | return ret; |
@@ -230,6 +232,7 @@ error_release: | |||
230 | error_put: | 232 | error_put: |
231 | module_put(dev->tr->owner); | 233 | module_put(dev->tr->owner); |
232 | kref_put(&dev->ref, blktrans_dev_release); | 234 | kref_put(&dev->ref, blktrans_dev_release); |
235 | mutex_unlock(&mtd_table_mutex); | ||
233 | mutex_unlock(&dev->lock); | 236 | mutex_unlock(&dev->lock); |
234 | blktrans_dev_put(dev); | 237 | blktrans_dev_put(dev); |
235 | return ret; | 238 | return ret; |
@@ -243,6 +246,7 @@ static void blktrans_release(struct gendisk *disk, fmode_t mode) | |||
243 | return; | 246 | return; |
244 | 247 | ||
245 | mutex_lock(&dev->lock); | 248 | mutex_lock(&dev->lock); |
249 | mutex_lock(&mtd_table_mutex); | ||
246 | 250 | ||
247 | if (--dev->open) | 251 | if (--dev->open) |
248 | goto unlock; | 252 | goto unlock; |
@@ -256,6 +260,7 @@ static void blktrans_release(struct gendisk *disk, fmode_t mode) | |||
256 | __put_mtd_device(dev->mtd); | 260 | __put_mtd_device(dev->mtd); |
257 | } | 261 | } |
258 | unlock: | 262 | unlock: |
263 | mutex_unlock(&mtd_table_mutex); | ||
259 | mutex_unlock(&dev->lock); | 264 | mutex_unlock(&dev->lock); |
260 | blktrans_dev_put(dev); | 265 | blktrans_dev_put(dev); |
261 | } | 266 | } |
@@ -273,7 +278,7 @@ static int blktrans_getgeo(struct block_device *bdev, struct hd_geometry *geo) | |||
273 | if (!dev->mtd) | 278 | if (!dev->mtd) |
274 | goto unlock; | 279 | goto unlock; |
275 | 280 | ||
276 | ret = dev->tr->getgeo ? dev->tr->getgeo(dev, geo) : 0; | 281 | ret = dev->tr->getgeo ? dev->tr->getgeo(dev, geo) : -ENOTTY; |
277 | unlock: | 282 | unlock: |
278 | mutex_unlock(&dev->lock); | 283 | mutex_unlock(&dev->lock); |
279 | blktrans_dev_put(dev); | 284 | blktrans_dev_put(dev); |
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index d172195fbd15..8bbbb751bf45 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c | |||
@@ -48,14 +48,34 @@ | |||
48 | static struct backing_dev_info mtd_bdi = { | 48 | static struct backing_dev_info mtd_bdi = { |
49 | }; | 49 | }; |
50 | 50 | ||
51 | static int mtd_cls_suspend(struct device *dev, pm_message_t state); | 51 | #ifdef CONFIG_PM_SLEEP |
52 | static int mtd_cls_resume(struct device *dev); | 52 | |
53 | static int mtd_cls_suspend(struct device *dev) | ||
54 | { | ||
55 | struct mtd_info *mtd = dev_get_drvdata(dev); | ||
56 | |||
57 | return mtd ? mtd_suspend(mtd) : 0; | ||
58 | } | ||
59 | |||
60 | static int mtd_cls_resume(struct device *dev) | ||
61 | { | ||
62 | struct mtd_info *mtd = dev_get_drvdata(dev); | ||
63 | |||
64 | if (mtd) | ||
65 | mtd_resume(mtd); | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static SIMPLE_DEV_PM_OPS(mtd_cls_pm_ops, mtd_cls_suspend, mtd_cls_resume); | ||
70 | #define MTD_CLS_PM_OPS (&mtd_cls_pm_ops) | ||
71 | #else | ||
72 | #define MTD_CLS_PM_OPS NULL | ||
73 | #endif | ||
53 | 74 | ||
54 | static struct class mtd_class = { | 75 | static struct class mtd_class = { |
55 | .name = "mtd", | 76 | .name = "mtd", |
56 | .owner = THIS_MODULE, | 77 | .owner = THIS_MODULE, |
57 | .suspend = mtd_cls_suspend, | 78 | .pm = MTD_CLS_PM_OPS, |
58 | .resume = mtd_cls_resume, | ||
59 | }; | 79 | }; |
60 | 80 | ||
61 | static DEFINE_IDR(mtd_idr); | 81 | static DEFINE_IDR(mtd_idr); |
@@ -88,22 +108,6 @@ static void mtd_release(struct device *dev) | |||
88 | device_destroy(&mtd_class, index + 1); | 108 | device_destroy(&mtd_class, index + 1); |
89 | } | 109 | } |
90 | 110 | ||
91 | static int mtd_cls_suspend(struct device *dev, pm_message_t state) | ||
92 | { | ||
93 | struct mtd_info *mtd = dev_get_drvdata(dev); | ||
94 | |||
95 | return mtd ? mtd_suspend(mtd) : 0; | ||
96 | } | ||
97 | |||
98 | static int mtd_cls_resume(struct device *dev) | ||
99 | { | ||
100 | struct mtd_info *mtd = dev_get_drvdata(dev); | ||
101 | |||
102 | if (mtd) | ||
103 | mtd_resume(mtd); | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static ssize_t mtd_type_show(struct device *dev, | 111 | static ssize_t mtd_type_show(struct device *dev, |
108 | struct device_attribute *attr, char *buf) | 112 | struct device_attribute *attr, char *buf) |
109 | { | 113 | { |
@@ -375,8 +379,7 @@ static int mtd_reboot_notifier(struct notifier_block *n, unsigned long state, | |||
375 | * | 379 | * |
376 | * Add a device to the list of MTD devices present in the system, and | 380 | * Add a device to the list of MTD devices present in the system, and |
377 | * notify each currently active MTD 'user' of its arrival. Returns | 381 | * notify each currently active MTD 'user' of its arrival. Returns |
378 | * zero on success or 1 on failure, which currently will only happen | 382 | * zero on success or non-zero on failure. |
379 | * if there is insufficient memory or a sysfs error. | ||
380 | */ | 383 | */ |
381 | 384 | ||
382 | int add_mtd_device(struct mtd_info *mtd) | 385 | int add_mtd_device(struct mtd_info *mtd) |
@@ -390,8 +393,10 @@ int add_mtd_device(struct mtd_info *mtd) | |||
390 | mutex_lock(&mtd_table_mutex); | 393 | mutex_lock(&mtd_table_mutex); |
391 | 394 | ||
392 | i = idr_alloc(&mtd_idr, mtd, 0, 0, GFP_KERNEL); | 395 | i = idr_alloc(&mtd_idr, mtd, 0, 0, GFP_KERNEL); |
393 | if (i < 0) | 396 | if (i < 0) { |
397 | error = i; | ||
394 | goto fail_locked; | 398 | goto fail_locked; |
399 | } | ||
395 | 400 | ||
396 | mtd->index = i; | 401 | mtd->index = i; |
397 | mtd->usecount = 0; | 402 | mtd->usecount = 0; |
@@ -420,6 +425,8 @@ int add_mtd_device(struct mtd_info *mtd) | |||
420 | printk(KERN_WARNING | 425 | printk(KERN_WARNING |
421 | "%s: unlock failed, writes may not work\n", | 426 | "%s: unlock failed, writes may not work\n", |
422 | mtd->name); | 427 | mtd->name); |
428 | /* Ignore unlock failures? */ | ||
429 | error = 0; | ||
423 | } | 430 | } |
424 | 431 | ||
425 | /* Caller should have set dev.parent to match the | 432 | /* Caller should have set dev.parent to match the |
@@ -430,7 +437,8 @@ int add_mtd_device(struct mtd_info *mtd) | |||
430 | mtd->dev.devt = MTD_DEVT(i); | 437 | mtd->dev.devt = MTD_DEVT(i); |
431 | dev_set_name(&mtd->dev, "mtd%d", i); | 438 | dev_set_name(&mtd->dev, "mtd%d", i); |
432 | dev_set_drvdata(&mtd->dev, mtd); | 439 | dev_set_drvdata(&mtd->dev, mtd); |
433 | if (device_register(&mtd->dev) != 0) | 440 | error = device_register(&mtd->dev); |
441 | if (error) | ||
434 | goto fail_added; | 442 | goto fail_added; |
435 | 443 | ||
436 | device_create(&mtd_class, mtd->dev.parent, MTD_DEVT(i) + 1, NULL, | 444 | device_create(&mtd_class, mtd->dev.parent, MTD_DEVT(i) + 1, NULL, |
@@ -454,7 +462,7 @@ fail_added: | |||
454 | idr_remove(&mtd_idr, i); | 462 | idr_remove(&mtd_idr, i); |
455 | fail_locked: | 463 | fail_locked: |
456 | mutex_unlock(&mtd_table_mutex); | 464 | mutex_unlock(&mtd_table_mutex); |
457 | return 1; | 465 | return error; |
458 | } | 466 | } |
459 | 467 | ||
460 | /** | 468 | /** |
@@ -510,8 +518,8 @@ static int mtd_add_device_partitions(struct mtd_info *mtd, | |||
510 | 518 | ||
511 | if (nbparts == 0 || IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) { | 519 | if (nbparts == 0 || IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) { |
512 | ret = add_mtd_device(mtd); | 520 | ret = add_mtd_device(mtd); |
513 | if (ret == 1) | 521 | if (ret) |
514 | return -ENODEV; | 522 | return ret; |
515 | } | 523 | } |
516 | 524 | ||
517 | if (nbparts > 0) { | 525 | if (nbparts > 0) { |
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 5897d8d8fa5a..5b2806a7e5f7 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -76,7 +76,7 @@ config MTD_NAND_DENALI_SCRATCH_REG_ADDR | |||
76 | 76 | ||
77 | config MTD_NAND_GPIO | 77 | config MTD_NAND_GPIO |
78 | tristate "GPIO assisted NAND Flash driver" | 78 | tristate "GPIO assisted NAND Flash driver" |
79 | depends on GPIOLIB | 79 | depends on GPIOLIB || COMPILE_TEST |
80 | help | 80 | help |
81 | This enables a NAND flash driver where control signals are | 81 | This enables a NAND flash driver where control signals are |
82 | connected to GPIO pins, and commands and data are communicated | 82 | connected to GPIO pins, and commands and data are communicated |
@@ -394,6 +394,14 @@ config MTD_NAND_GPMI_NAND | |||
394 | block, such as SD card. So pay attention to it when you enable | 394 | block, such as SD card. So pay attention to it when you enable |
395 | the GPMI. | 395 | the GPMI. |
396 | 396 | ||
397 | config MTD_NAND_BRCMNAND | ||
398 | tristate "Broadcom STB NAND controller" | ||
399 | depends on ARM || MIPS | ||
400 | help | ||
401 | Enables the Broadcom NAND controller driver. The controller was | ||
402 | originally designed for Set-Top Box but is used on various BCM7xxx, | ||
403 | BCM3xxx, BCM63xxx, iProc/Cygnus and more. | ||
404 | |||
397 | config MTD_NAND_BCM47XXNFLASH | 405 | config MTD_NAND_BCM47XXNFLASH |
398 | tristate "Support for NAND flash on BCM4706 BCMA bus" | 406 | tristate "Support for NAND flash on BCM4706 BCMA bus" |
399 | depends on BCMA_NFLASH | 407 | depends on BCMA_NFLASH |
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 582bbd05aff7..1f897ec3c242 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile | |||
@@ -52,5 +52,6 @@ obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o | |||
52 | obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ | 52 | obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ |
53 | obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_nand.o | 53 | obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_nand.o |
54 | obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o | 54 | obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o |
55 | obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/ | ||
55 | 56 | ||
56 | nand-objs := nand_base.o nand_bbt.o nand_timings.o | 57 | nand-objs := nand_base.o nand_bbt.o nand_timings.o |
diff --git a/drivers/mtd/nand/brcmnand/Makefile b/drivers/mtd/nand/brcmnand/Makefile new file mode 100644 index 000000000000..3b1fbfd27d4f --- /dev/null +++ b/drivers/mtd/nand/brcmnand/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # link order matters; don't link the more generic brcmstb_nand.o before the | ||
2 | # more specific iproc_nand.o, for instance | ||
3 | obj-$(CONFIG_MTD_NAND_BRCMNAND) += iproc_nand.o | ||
4 | obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63138_nand.o | ||
5 | obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmstb_nand.o | ||
6 | obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.o | ||
diff --git a/drivers/mtd/nand/brcmnand/bcm63138_nand.c b/drivers/mtd/nand/brcmnand/bcm63138_nand.c new file mode 100644 index 000000000000..3f4c44c24e14 --- /dev/null +++ b/drivers/mtd/nand/brcmnand/bcm63138_nand.c | |||
@@ -0,0 +1,111 @@ | |||
1 | /* | ||
2 | * Copyright © 2015 Broadcom Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/ioport.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/of_address.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/slab.h> | ||
22 | |||
23 | #include "brcmnand.h" | ||
24 | |||
25 | struct bcm63138_nand_soc_priv { | ||
26 | void __iomem *base; | ||
27 | }; | ||
28 | |||
29 | #define BCM63138_NAND_INT_STATUS 0x00 | ||
30 | #define BCM63138_NAND_INT_EN 0x04 | ||
31 | |||
32 | enum { | ||
33 | BCM63138_CTLRDY = BIT(4), | ||
34 | }; | ||
35 | |||
36 | static bool bcm63138_nand_intc_ack(struct brcmnand_soc *soc) | ||
37 | { | ||
38 | struct bcm63138_nand_soc_priv *priv = soc->priv; | ||
39 | void __iomem *mmio = priv->base + BCM63138_NAND_INT_STATUS; | ||
40 | u32 val = brcmnand_readl(mmio); | ||
41 | |||
42 | if (val & BCM63138_CTLRDY) { | ||
43 | brcmnand_writel(val & ~BCM63138_CTLRDY, mmio); | ||
44 | return true; | ||
45 | } | ||
46 | |||
47 | return false; | ||
48 | } | ||
49 | |||
50 | static void bcm63138_nand_intc_set(struct brcmnand_soc *soc, bool en) | ||
51 | { | ||
52 | struct bcm63138_nand_soc_priv *priv = soc->priv; | ||
53 | void __iomem *mmio = priv->base + BCM63138_NAND_INT_EN; | ||
54 | u32 val = brcmnand_readl(mmio); | ||
55 | |||
56 | if (en) | ||
57 | val |= BCM63138_CTLRDY; | ||
58 | else | ||
59 | val &= ~BCM63138_CTLRDY; | ||
60 | |||
61 | brcmnand_writel(val, mmio); | ||
62 | } | ||
63 | |||
64 | static int bcm63138_nand_probe(struct platform_device *pdev) | ||
65 | { | ||
66 | struct device *dev = &pdev->dev; | ||
67 | struct bcm63138_nand_soc_priv *priv; | ||
68 | struct brcmnand_soc *soc; | ||
69 | struct resource *res; | ||
70 | |||
71 | soc = devm_kzalloc(dev, sizeof(*soc), GFP_KERNEL); | ||
72 | if (!soc) | ||
73 | return -ENOMEM; | ||
74 | |||
75 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
76 | if (!priv) | ||
77 | return -ENOMEM; | ||
78 | |||
79 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand-int-base"); | ||
80 | priv->base = devm_ioremap_resource(dev, res); | ||
81 | if (IS_ERR(priv->base)) | ||
82 | return PTR_ERR(priv->base); | ||
83 | |||
84 | soc->pdev = pdev; | ||
85 | soc->priv = priv; | ||
86 | soc->ctlrdy_ack = bcm63138_nand_intc_ack; | ||
87 | soc->ctlrdy_set_enabled = bcm63138_nand_intc_set; | ||
88 | |||
89 | return brcmnand_probe(pdev, soc); | ||
90 | } | ||
91 | |||
92 | static const struct of_device_id bcm63138_nand_of_match[] = { | ||
93 | { .compatible = "brcm,nand-bcm63138" }, | ||
94 | {}, | ||
95 | }; | ||
96 | MODULE_DEVICE_TABLE(of, bcm63138_nand_of_match); | ||
97 | |||
98 | static struct platform_driver bcm63138_nand_driver = { | ||
99 | .probe = bcm63138_nand_probe, | ||
100 | .remove = brcmnand_remove, | ||
101 | .driver = { | ||
102 | .name = "bcm63138_nand", | ||
103 | .pm = &brcmnand_pm_ops, | ||
104 | .of_match_table = bcm63138_nand_of_match, | ||
105 | } | ||
106 | }; | ||
107 | module_platform_driver(bcm63138_nand_driver); | ||
108 | |||
109 | MODULE_LICENSE("GPL v2"); | ||
110 | MODULE_AUTHOR("Brian Norris"); | ||
111 | MODULE_DESCRIPTION("NAND driver for BCM63138"); | ||
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c new file mode 100644 index 000000000000..fddb795eeb71 --- /dev/null +++ b/drivers/mtd/nand/brcmnand/brcmnand.c | |||
@@ -0,0 +1,2246 @@ | |||
1 | /* | ||
2 | * Copyright © 2010-2015 Broadcom Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | #include <linux/version.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/completion.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/spinlock.h> | ||
24 | #include <linux/dma-mapping.h> | ||
25 | #include <linux/ioport.h> | ||
26 | #include <linux/bug.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/bitops.h> | ||
29 | #include <linux/mm.h> | ||
30 | #include <linux/mtd/mtd.h> | ||
31 | #include <linux/mtd/nand.h> | ||
32 | #include <linux/mtd/partitions.h> | ||
33 | #include <linux/of.h> | ||
34 | #include <linux/of_mtd.h> | ||
35 | #include <linux/of_platform.h> | ||
36 | #include <linux/slab.h> | ||
37 | #include <linux/list.h> | ||
38 | #include <linux/log2.h> | ||
39 | |||
40 | #include "brcmnand.h" | ||
41 | |||
42 | /* | ||
43 | * This flag controls if WP stays on between erase/write commands to mitigate | ||
44 | * flash corruption due to power glitches. Values: | ||
45 | * 0: NAND_WP is not used or not available | ||
46 | * 1: NAND_WP is set by default, cleared for erase/write operations | ||
47 | * 2: NAND_WP is always cleared | ||
48 | */ | ||
49 | static int wp_on = 1; | ||
50 | module_param(wp_on, int, 0444); | ||
51 | |||
52 | /*********************************************************************** | ||
53 | * Definitions | ||
54 | ***********************************************************************/ | ||
55 | |||
56 | #define DRV_NAME "brcmnand" | ||
57 | |||
58 | #define CMD_NULL 0x00 | ||
59 | #define CMD_PAGE_READ 0x01 | ||
60 | #define CMD_SPARE_AREA_READ 0x02 | ||
61 | #define CMD_STATUS_READ 0x03 | ||
62 | #define CMD_PROGRAM_PAGE 0x04 | ||
63 | #define CMD_PROGRAM_SPARE_AREA 0x05 | ||
64 | #define CMD_COPY_BACK 0x06 | ||
65 | #define CMD_DEVICE_ID_READ 0x07 | ||
66 | #define CMD_BLOCK_ERASE 0x08 | ||
67 | #define CMD_FLASH_RESET 0x09 | ||
68 | #define CMD_BLOCKS_LOCK 0x0a | ||
69 | #define CMD_BLOCKS_LOCK_DOWN 0x0b | ||
70 | #define CMD_BLOCKS_UNLOCK 0x0c | ||
71 | #define CMD_READ_BLOCKS_LOCK_STATUS 0x0d | ||
72 | #define CMD_PARAMETER_READ 0x0e | ||
73 | #define CMD_PARAMETER_CHANGE_COL 0x0f | ||
74 | #define CMD_LOW_LEVEL_OP 0x10 | ||
75 | |||
76 | struct brcm_nand_dma_desc { | ||
77 | u32 next_desc; | ||
78 | u32 next_desc_ext; | ||
79 | u32 cmd_irq; | ||
80 | u32 dram_addr; | ||
81 | u32 dram_addr_ext; | ||
82 | u32 tfr_len; | ||
83 | u32 total_len; | ||
84 | u32 flash_addr; | ||
85 | u32 flash_addr_ext; | ||
86 | u32 cs; | ||
87 | u32 pad2[5]; | ||
88 | u32 status_valid; | ||
89 | } __packed; | ||
90 | |||
91 | /* Bitfields for brcm_nand_dma_desc::status_valid */ | ||
92 | #define FLASH_DMA_ECC_ERROR (1 << 8) | ||
93 | #define FLASH_DMA_CORR_ERROR (1 << 9) | ||
94 | |||
95 | /* 512B flash cache in the NAND controller HW */ | ||
96 | #define FC_SHIFT 9U | ||
97 | #define FC_BYTES 512U | ||
98 | #define FC_WORDS (FC_BYTES >> 2) | ||
99 | |||
100 | #define BRCMNAND_MIN_PAGESIZE 512 | ||
101 | #define BRCMNAND_MIN_BLOCKSIZE (8 * 1024) | ||
102 | #define BRCMNAND_MIN_DEVSIZE (4ULL * 1024 * 1024) | ||
103 | |||
104 | /* Controller feature flags */ | ||
105 | enum { | ||
106 | BRCMNAND_HAS_1K_SECTORS = BIT(0), | ||
107 | BRCMNAND_HAS_PREFETCH = BIT(1), | ||
108 | BRCMNAND_HAS_CACHE_MODE = BIT(2), | ||
109 | BRCMNAND_HAS_WP = BIT(3), | ||
110 | }; | ||
111 | |||
112 | struct brcmnand_controller { | ||
113 | struct device *dev; | ||
114 | struct nand_hw_control controller; | ||
115 | void __iomem *nand_base; | ||
116 | void __iomem *nand_fc; /* flash cache */ | ||
117 | void __iomem *flash_dma_base; | ||
118 | unsigned int irq; | ||
119 | unsigned int dma_irq; | ||
120 | int nand_version; | ||
121 | |||
122 | /* Some SoCs provide custom interrupt status register(s) */ | ||
123 | struct brcmnand_soc *soc; | ||
124 | |||
125 | int cmd_pending; | ||
126 | bool dma_pending; | ||
127 | struct completion done; | ||
128 | struct completion dma_done; | ||
129 | |||
130 | /* List of NAND hosts (one for each chip-select) */ | ||
131 | struct list_head host_list; | ||
132 | |||
133 | struct brcm_nand_dma_desc *dma_desc; | ||
134 | dma_addr_t dma_pa; | ||
135 | |||
136 | /* in-memory cache of the FLASH_CACHE, used only for some commands */ | ||
137 | u32 flash_cache[FC_WORDS]; | ||
138 | |||
139 | /* Controller revision details */ | ||
140 | const u16 *reg_offsets; | ||
141 | unsigned int reg_spacing; /* between CS1, CS2, ... regs */ | ||
142 | const u8 *cs_offsets; /* within each chip-select */ | ||
143 | const u8 *cs0_offsets; /* within CS0, if different */ | ||
144 | unsigned int max_block_size; | ||
145 | const unsigned int *block_sizes; | ||
146 | unsigned int max_page_size; | ||
147 | const unsigned int *page_sizes; | ||
148 | unsigned int max_oob; | ||
149 | u32 features; | ||
150 | |||
151 | /* for low-power standby/resume only */ | ||
152 | u32 nand_cs_nand_select; | ||
153 | u32 nand_cs_nand_xor; | ||
154 | u32 corr_stat_threshold; | ||
155 | u32 flash_dma_mode; | ||
156 | }; | ||
157 | |||
158 | struct brcmnand_cfg { | ||
159 | u64 device_size; | ||
160 | unsigned int block_size; | ||
161 | unsigned int page_size; | ||
162 | unsigned int spare_area_size; | ||
163 | unsigned int device_width; | ||
164 | unsigned int col_adr_bytes; | ||
165 | unsigned int blk_adr_bytes; | ||
166 | unsigned int ful_adr_bytes; | ||
167 | unsigned int sector_size_1k; | ||
168 | unsigned int ecc_level; | ||
169 | /* use for low-power standby/resume only */ | ||
170 | u32 acc_control; | ||
171 | u32 config; | ||
172 | u32 config_ext; | ||
173 | u32 timing_1; | ||
174 | u32 timing_2; | ||
175 | }; | ||
176 | |||
177 | struct brcmnand_host { | ||
178 | struct list_head node; | ||
179 | struct device_node *of_node; | ||
180 | |||
181 | struct nand_chip chip; | ||
182 | struct mtd_info mtd; | ||
183 | struct platform_device *pdev; | ||
184 | int cs; | ||
185 | |||
186 | unsigned int last_cmd; | ||
187 | unsigned int last_byte; | ||
188 | u64 last_addr; | ||
189 | struct brcmnand_cfg hwcfg; | ||
190 | struct brcmnand_controller *ctrl; | ||
191 | }; | ||
192 | |||
193 | enum brcmnand_reg { | ||
194 | BRCMNAND_CMD_START = 0, | ||
195 | BRCMNAND_CMD_EXT_ADDRESS, | ||
196 | BRCMNAND_CMD_ADDRESS, | ||
197 | BRCMNAND_INTFC_STATUS, | ||
198 | BRCMNAND_CS_SELECT, | ||
199 | BRCMNAND_CS_XOR, | ||
200 | BRCMNAND_LL_OP, | ||
201 | BRCMNAND_CS0_BASE, | ||
202 | BRCMNAND_CS1_BASE, /* CS1 regs, if non-contiguous */ | ||
203 | BRCMNAND_CORR_THRESHOLD, | ||
204 | BRCMNAND_CORR_THRESHOLD_EXT, | ||
205 | BRCMNAND_UNCORR_COUNT, | ||
206 | BRCMNAND_CORR_COUNT, | ||
207 | BRCMNAND_CORR_EXT_ADDR, | ||
208 | BRCMNAND_CORR_ADDR, | ||
209 | BRCMNAND_UNCORR_EXT_ADDR, | ||
210 | BRCMNAND_UNCORR_ADDR, | ||
211 | BRCMNAND_SEMAPHORE, | ||
212 | BRCMNAND_ID, | ||
213 | BRCMNAND_ID_EXT, | ||
214 | BRCMNAND_LL_RDATA, | ||
215 | BRCMNAND_OOB_READ_BASE, | ||
216 | BRCMNAND_OOB_READ_10_BASE, /* offset 0x10, if non-contiguous */ | ||
217 | BRCMNAND_OOB_WRITE_BASE, | ||
218 | BRCMNAND_OOB_WRITE_10_BASE, /* offset 0x10, if non-contiguous */ | ||
219 | BRCMNAND_FC_BASE, | ||
220 | }; | ||
221 | |||
222 | /* BRCMNAND v4.0 */ | ||
223 | static const u16 brcmnand_regs_v40[] = { | ||
224 | [BRCMNAND_CMD_START] = 0x04, | ||
225 | [BRCMNAND_CMD_EXT_ADDRESS] = 0x08, | ||
226 | [BRCMNAND_CMD_ADDRESS] = 0x0c, | ||
227 | [BRCMNAND_INTFC_STATUS] = 0x6c, | ||
228 | [BRCMNAND_CS_SELECT] = 0x14, | ||
229 | [BRCMNAND_CS_XOR] = 0x18, | ||
230 | [BRCMNAND_LL_OP] = 0x178, | ||
231 | [BRCMNAND_CS0_BASE] = 0x40, | ||
232 | [BRCMNAND_CS1_BASE] = 0xd0, | ||
233 | [BRCMNAND_CORR_THRESHOLD] = 0x84, | ||
234 | [BRCMNAND_CORR_THRESHOLD_EXT] = 0, | ||
235 | [BRCMNAND_UNCORR_COUNT] = 0, | ||
236 | [BRCMNAND_CORR_COUNT] = 0, | ||
237 | [BRCMNAND_CORR_EXT_ADDR] = 0x70, | ||
238 | [BRCMNAND_CORR_ADDR] = 0x74, | ||
239 | [BRCMNAND_UNCORR_EXT_ADDR] = 0x78, | ||
240 | [BRCMNAND_UNCORR_ADDR] = 0x7c, | ||
241 | [BRCMNAND_SEMAPHORE] = 0x58, | ||
242 | [BRCMNAND_ID] = 0x60, | ||
243 | [BRCMNAND_ID_EXT] = 0x64, | ||
244 | [BRCMNAND_LL_RDATA] = 0x17c, | ||
245 | [BRCMNAND_OOB_READ_BASE] = 0x20, | ||
246 | [BRCMNAND_OOB_READ_10_BASE] = 0x130, | ||
247 | [BRCMNAND_OOB_WRITE_BASE] = 0x30, | ||
248 | [BRCMNAND_OOB_WRITE_10_BASE] = 0, | ||
249 | [BRCMNAND_FC_BASE] = 0x200, | ||
250 | }; | ||
251 | |||
252 | /* BRCMNAND v5.0 */ | ||
253 | static const u16 brcmnand_regs_v50[] = { | ||
254 | [BRCMNAND_CMD_START] = 0x04, | ||
255 | [BRCMNAND_CMD_EXT_ADDRESS] = 0x08, | ||
256 | [BRCMNAND_CMD_ADDRESS] = 0x0c, | ||
257 | [BRCMNAND_INTFC_STATUS] = 0x6c, | ||
258 | [BRCMNAND_CS_SELECT] = 0x14, | ||
259 | [BRCMNAND_CS_XOR] = 0x18, | ||
260 | [BRCMNAND_LL_OP] = 0x178, | ||
261 | [BRCMNAND_CS0_BASE] = 0x40, | ||
262 | [BRCMNAND_CS1_BASE] = 0xd0, | ||
263 | [BRCMNAND_CORR_THRESHOLD] = 0x84, | ||
264 | [BRCMNAND_CORR_THRESHOLD_EXT] = 0, | ||
265 | [BRCMNAND_UNCORR_COUNT] = 0, | ||
266 | [BRCMNAND_CORR_COUNT] = 0, | ||
267 | [BRCMNAND_CORR_EXT_ADDR] = 0x70, | ||
268 | [BRCMNAND_CORR_ADDR] = 0x74, | ||
269 | [BRCMNAND_UNCORR_EXT_ADDR] = 0x78, | ||
270 | [BRCMNAND_UNCORR_ADDR] = 0x7c, | ||
271 | [BRCMNAND_SEMAPHORE] = 0x58, | ||
272 | [BRCMNAND_ID] = 0x60, | ||
273 | [BRCMNAND_ID_EXT] = 0x64, | ||
274 | [BRCMNAND_LL_RDATA] = 0x17c, | ||
275 | [BRCMNAND_OOB_READ_BASE] = 0x20, | ||
276 | [BRCMNAND_OOB_READ_10_BASE] = 0x130, | ||
277 | [BRCMNAND_OOB_WRITE_BASE] = 0x30, | ||
278 | [BRCMNAND_OOB_WRITE_10_BASE] = 0x140, | ||
279 | [BRCMNAND_FC_BASE] = 0x200, | ||
280 | }; | ||
281 | |||
282 | /* BRCMNAND v6.0 - v7.1 */ | ||
283 | static const u16 brcmnand_regs_v60[] = { | ||
284 | [BRCMNAND_CMD_START] = 0x04, | ||
285 | [BRCMNAND_CMD_EXT_ADDRESS] = 0x08, | ||
286 | [BRCMNAND_CMD_ADDRESS] = 0x0c, | ||
287 | [BRCMNAND_INTFC_STATUS] = 0x14, | ||
288 | [BRCMNAND_CS_SELECT] = 0x18, | ||
289 | [BRCMNAND_CS_XOR] = 0x1c, | ||
290 | [BRCMNAND_LL_OP] = 0x20, | ||
291 | [BRCMNAND_CS0_BASE] = 0x50, | ||
292 | [BRCMNAND_CS1_BASE] = 0, | ||
293 | [BRCMNAND_CORR_THRESHOLD] = 0xc0, | ||
294 | [BRCMNAND_CORR_THRESHOLD_EXT] = 0xc4, | ||
295 | [BRCMNAND_UNCORR_COUNT] = 0xfc, | ||
296 | [BRCMNAND_CORR_COUNT] = 0x100, | ||
297 | [BRCMNAND_CORR_EXT_ADDR] = 0x10c, | ||
298 | [BRCMNAND_CORR_ADDR] = 0x110, | ||
299 | [BRCMNAND_UNCORR_EXT_ADDR] = 0x114, | ||
300 | [BRCMNAND_UNCORR_ADDR] = 0x118, | ||
301 | [BRCMNAND_SEMAPHORE] = 0x150, | ||
302 | [BRCMNAND_ID] = 0x194, | ||
303 | [BRCMNAND_ID_EXT] = 0x198, | ||
304 | [BRCMNAND_LL_RDATA] = 0x19c, | ||
305 | [BRCMNAND_OOB_READ_BASE] = 0x200, | ||
306 | [BRCMNAND_OOB_READ_10_BASE] = 0, | ||
307 | [BRCMNAND_OOB_WRITE_BASE] = 0x280, | ||
308 | [BRCMNAND_OOB_WRITE_10_BASE] = 0, | ||
309 | [BRCMNAND_FC_BASE] = 0x400, | ||
310 | }; | ||
311 | |||
312 | enum brcmnand_cs_reg { | ||
313 | BRCMNAND_CS_CFG_EXT = 0, | ||
314 | BRCMNAND_CS_CFG, | ||
315 | BRCMNAND_CS_ACC_CONTROL, | ||
316 | BRCMNAND_CS_TIMING1, | ||
317 | BRCMNAND_CS_TIMING2, | ||
318 | }; | ||
319 | |||
320 | /* Per chip-select offsets for v7.1 */ | ||
321 | static const u8 brcmnand_cs_offsets_v71[] = { | ||
322 | [BRCMNAND_CS_ACC_CONTROL] = 0x00, | ||
323 | [BRCMNAND_CS_CFG_EXT] = 0x04, | ||
324 | [BRCMNAND_CS_CFG] = 0x08, | ||
325 | [BRCMNAND_CS_TIMING1] = 0x0c, | ||
326 | [BRCMNAND_CS_TIMING2] = 0x10, | ||
327 | }; | ||
328 | |||
329 | /* Per chip-select offsets for pre v7.1, except CS0 on <= v5.0 */ | ||
330 | static const u8 brcmnand_cs_offsets[] = { | ||
331 | [BRCMNAND_CS_ACC_CONTROL] = 0x00, | ||
332 | [BRCMNAND_CS_CFG_EXT] = 0x04, | ||
333 | [BRCMNAND_CS_CFG] = 0x04, | ||
334 | [BRCMNAND_CS_TIMING1] = 0x08, | ||
335 | [BRCMNAND_CS_TIMING2] = 0x0c, | ||
336 | }; | ||
337 | |||
338 | /* Per chip-select offset for <= v5.0 on CS0 only */ | ||
339 | static const u8 brcmnand_cs_offsets_cs0[] = { | ||
340 | [BRCMNAND_CS_ACC_CONTROL] = 0x00, | ||
341 | [BRCMNAND_CS_CFG_EXT] = 0x08, | ||
342 | [BRCMNAND_CS_CFG] = 0x08, | ||
343 | [BRCMNAND_CS_TIMING1] = 0x10, | ||
344 | [BRCMNAND_CS_TIMING2] = 0x14, | ||
345 | }; | ||
346 | |||
347 | /* BRCMNAND_INTFC_STATUS */ | ||
348 | enum { | ||
349 | INTFC_FLASH_STATUS = GENMASK(7, 0), | ||
350 | |||
351 | INTFC_ERASED = BIT(27), | ||
352 | INTFC_OOB_VALID = BIT(28), | ||
353 | INTFC_CACHE_VALID = BIT(29), | ||
354 | INTFC_FLASH_READY = BIT(30), | ||
355 | INTFC_CTLR_READY = BIT(31), | ||
356 | }; | ||
357 | |||
358 | static inline u32 nand_readreg(struct brcmnand_controller *ctrl, u32 offs) | ||
359 | { | ||
360 | return brcmnand_readl(ctrl->nand_base + offs); | ||
361 | } | ||
362 | |||
363 | static inline void nand_writereg(struct brcmnand_controller *ctrl, u32 offs, | ||
364 | u32 val) | ||
365 | { | ||
366 | brcmnand_writel(val, ctrl->nand_base + offs); | ||
367 | } | ||
368 | |||
369 | static int brcmnand_revision_init(struct brcmnand_controller *ctrl) | ||
370 | { | ||
371 | static const unsigned int block_sizes_v6[] = { 8, 16, 128, 256, 512, 1024, 2048, 0 }; | ||
372 | static const unsigned int block_sizes_v4[] = { 16, 128, 8, 512, 256, 1024, 2048, 0 }; | ||
373 | static const unsigned int page_sizes[] = { 512, 2048, 4096, 8192, 0 }; | ||
374 | |||
375 | ctrl->nand_version = nand_readreg(ctrl, 0) & 0xffff; | ||
376 | |||
377 | /* Only support v4.0+? */ | ||
378 | if (ctrl->nand_version < 0x0400) { | ||
379 | dev_err(ctrl->dev, "version %#x not supported\n", | ||
380 | ctrl->nand_version); | ||
381 | return -ENODEV; | ||
382 | } | ||
383 | |||
384 | /* Register offsets */ | ||
385 | if (ctrl->nand_version >= 0x0600) | ||
386 | ctrl->reg_offsets = brcmnand_regs_v60; | ||
387 | else if (ctrl->nand_version >= 0x0500) | ||
388 | ctrl->reg_offsets = brcmnand_regs_v50; | ||
389 | else if (ctrl->nand_version >= 0x0400) | ||
390 | ctrl->reg_offsets = brcmnand_regs_v40; | ||
391 | |||
392 | /* Chip-select stride */ | ||
393 | if (ctrl->nand_version >= 0x0701) | ||
394 | ctrl->reg_spacing = 0x14; | ||
395 | else | ||
396 | ctrl->reg_spacing = 0x10; | ||
397 | |||
398 | /* Per chip-select registers */ | ||
399 | if (ctrl->nand_version >= 0x0701) { | ||
400 | ctrl->cs_offsets = brcmnand_cs_offsets_v71; | ||
401 | } else { | ||
402 | ctrl->cs_offsets = brcmnand_cs_offsets; | ||
403 | |||
404 | /* v5.0 and earlier has a different CS0 offset layout */ | ||
405 | if (ctrl->nand_version <= 0x0500) | ||
406 | ctrl->cs0_offsets = brcmnand_cs_offsets_cs0; | ||
407 | } | ||
408 | |||
409 | /* Page / block sizes */ | ||
410 | if (ctrl->nand_version >= 0x0701) { | ||
411 | /* >= v7.1 use nice power-of-2 values! */ | ||
412 | ctrl->max_page_size = 16 * 1024; | ||
413 | ctrl->max_block_size = 2 * 1024 * 1024; | ||
414 | } else { | ||
415 | ctrl->page_sizes = page_sizes; | ||
416 | if (ctrl->nand_version >= 0x0600) | ||
417 | ctrl->block_sizes = block_sizes_v6; | ||
418 | else | ||
419 | ctrl->block_sizes = block_sizes_v4; | ||
420 | |||
421 | if (ctrl->nand_version < 0x0400) { | ||
422 | ctrl->max_page_size = 4096; | ||
423 | ctrl->max_block_size = 512 * 1024; | ||
424 | } | ||
425 | } | ||
426 | |||
427 | /* Maximum spare area sector size (per 512B) */ | ||
428 | if (ctrl->nand_version >= 0x0600) | ||
429 | ctrl->max_oob = 64; | ||
430 | else if (ctrl->nand_version >= 0x0500) | ||
431 | ctrl->max_oob = 32; | ||
432 | else | ||
433 | ctrl->max_oob = 16; | ||
434 | |||
435 | /* v6.0 and newer (except v6.1) have prefetch support */ | ||
436 | if (ctrl->nand_version >= 0x0600 && ctrl->nand_version != 0x0601) | ||
437 | ctrl->features |= BRCMNAND_HAS_PREFETCH; | ||
438 | |||
439 | /* | ||
440 | * v6.x has cache mode, but it's implemented differently. Ignore it for | ||
441 | * now. | ||
442 | */ | ||
443 | if (ctrl->nand_version >= 0x0700) | ||
444 | ctrl->features |= BRCMNAND_HAS_CACHE_MODE; | ||
445 | |||
446 | if (ctrl->nand_version >= 0x0500) | ||
447 | ctrl->features |= BRCMNAND_HAS_1K_SECTORS; | ||
448 | |||
449 | if (ctrl->nand_version >= 0x0700) | ||
450 | ctrl->features |= BRCMNAND_HAS_WP; | ||
451 | else if (of_property_read_bool(ctrl->dev->of_node, "brcm,nand-has-wp")) | ||
452 | ctrl->features |= BRCMNAND_HAS_WP; | ||
453 | |||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | static inline u32 brcmnand_read_reg(struct brcmnand_controller *ctrl, | ||
458 | enum brcmnand_reg reg) | ||
459 | { | ||
460 | u16 offs = ctrl->reg_offsets[reg]; | ||
461 | |||
462 | if (offs) | ||
463 | return nand_readreg(ctrl, offs); | ||
464 | else | ||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | static inline void brcmnand_write_reg(struct brcmnand_controller *ctrl, | ||
469 | enum brcmnand_reg reg, u32 val) | ||
470 | { | ||
471 | u16 offs = ctrl->reg_offsets[reg]; | ||
472 | |||
473 | if (offs) | ||
474 | nand_writereg(ctrl, offs, val); | ||
475 | } | ||
476 | |||
477 | static inline void brcmnand_rmw_reg(struct brcmnand_controller *ctrl, | ||
478 | enum brcmnand_reg reg, u32 mask, unsigned | ||
479 | int shift, u32 val) | ||
480 | { | ||
481 | u32 tmp = brcmnand_read_reg(ctrl, reg); | ||
482 | |||
483 | tmp &= ~mask; | ||
484 | tmp |= val << shift; | ||
485 | brcmnand_write_reg(ctrl, reg, tmp); | ||
486 | } | ||
487 | |||
488 | static inline u32 brcmnand_read_fc(struct brcmnand_controller *ctrl, int word) | ||
489 | { | ||
490 | return __raw_readl(ctrl->nand_fc + word * 4); | ||
491 | } | ||
492 | |||
493 | static inline void brcmnand_write_fc(struct brcmnand_controller *ctrl, | ||
494 | int word, u32 val) | ||
495 | { | ||
496 | __raw_writel(val, ctrl->nand_fc + word * 4); | ||
497 | } | ||
498 | |||
499 | static inline u16 brcmnand_cs_offset(struct brcmnand_controller *ctrl, int cs, | ||
500 | enum brcmnand_cs_reg reg) | ||
501 | { | ||
502 | u16 offs_cs0 = ctrl->reg_offsets[BRCMNAND_CS0_BASE]; | ||
503 | u16 offs_cs1 = ctrl->reg_offsets[BRCMNAND_CS1_BASE]; | ||
504 | u8 cs_offs; | ||
505 | |||
506 | if (cs == 0 && ctrl->cs0_offsets) | ||
507 | cs_offs = ctrl->cs0_offsets[reg]; | ||
508 | else | ||
509 | cs_offs = ctrl->cs_offsets[reg]; | ||
510 | |||
511 | if (cs && offs_cs1) | ||
512 | return offs_cs1 + (cs - 1) * ctrl->reg_spacing + cs_offs; | ||
513 | |||
514 | return offs_cs0 + cs * ctrl->reg_spacing + cs_offs; | ||
515 | } | ||
516 | |||
517 | static inline u32 brcmnand_count_corrected(struct brcmnand_controller *ctrl) | ||
518 | { | ||
519 | if (ctrl->nand_version < 0x0600) | ||
520 | return 1; | ||
521 | return brcmnand_read_reg(ctrl, BRCMNAND_CORR_COUNT); | ||
522 | } | ||
523 | |||
524 | static void brcmnand_wr_corr_thresh(struct brcmnand_host *host, u8 val) | ||
525 | { | ||
526 | struct brcmnand_controller *ctrl = host->ctrl; | ||
527 | unsigned int shift = 0, bits; | ||
528 | enum brcmnand_reg reg = BRCMNAND_CORR_THRESHOLD; | ||
529 | int cs = host->cs; | ||
530 | |||
531 | if (ctrl->nand_version >= 0x0600) | ||
532 | bits = 6; | ||
533 | else if (ctrl->nand_version >= 0x0500) | ||
534 | bits = 5; | ||
535 | else | ||
536 | bits = 4; | ||
537 | |||
538 | if (ctrl->nand_version >= 0x0600) { | ||
539 | if (cs >= 5) | ||
540 | reg = BRCMNAND_CORR_THRESHOLD_EXT; | ||
541 | shift = (cs % 5) * bits; | ||
542 | } | ||
543 | brcmnand_rmw_reg(ctrl, reg, (bits - 1) << shift, shift, val); | ||
544 | } | ||
545 | |||
546 | static inline int brcmnand_cmd_shift(struct brcmnand_controller *ctrl) | ||
547 | { | ||
548 | if (ctrl->nand_version < 0x0700) | ||
549 | return 24; | ||
550 | return 0; | ||
551 | } | ||
552 | |||
553 | /*********************************************************************** | ||
554 | * NAND ACC CONTROL bitfield | ||
555 | * | ||
556 | * Some bits have remained constant throughout hardware revision, while | ||
557 | * others have shifted around. | ||
558 | ***********************************************************************/ | ||
559 | |||
560 | /* Constant for all versions (where supported) */ | ||
561 | enum { | ||
562 | /* See BRCMNAND_HAS_CACHE_MODE */ | ||
563 | ACC_CONTROL_CACHE_MODE = BIT(22), | ||
564 | |||
565 | /* See BRCMNAND_HAS_PREFETCH */ | ||
566 | ACC_CONTROL_PREFETCH = BIT(23), | ||
567 | |||
568 | ACC_CONTROL_PAGE_HIT = BIT(24), | ||
569 | ACC_CONTROL_WR_PREEMPT = BIT(25), | ||
570 | ACC_CONTROL_PARTIAL_PAGE = BIT(26), | ||
571 | ACC_CONTROL_RD_ERASED = BIT(27), | ||
572 | ACC_CONTROL_FAST_PGM_RDIN = BIT(28), | ||
573 | ACC_CONTROL_WR_ECC = BIT(30), | ||
574 | ACC_CONTROL_RD_ECC = BIT(31), | ||
575 | }; | ||
576 | |||
577 | static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl) | ||
578 | { | ||
579 | if (ctrl->nand_version >= 0x0600) | ||
580 | return GENMASK(6, 0); | ||
581 | else | ||
582 | return GENMASK(5, 0); | ||
583 | } | ||
584 | |||
585 | #define NAND_ACC_CONTROL_ECC_SHIFT 16 | ||
586 | |||
587 | static inline u32 brcmnand_ecc_level_mask(struct brcmnand_controller *ctrl) | ||
588 | { | ||
589 | u32 mask = (ctrl->nand_version >= 0x0600) ? 0x1f : 0x0f; | ||
590 | |||
591 | return mask << NAND_ACC_CONTROL_ECC_SHIFT; | ||
592 | } | ||
593 | |||
594 | static void brcmnand_set_ecc_enabled(struct brcmnand_host *host, int en) | ||
595 | { | ||
596 | struct brcmnand_controller *ctrl = host->ctrl; | ||
597 | u16 offs = brcmnand_cs_offset(ctrl, host->cs, BRCMNAND_CS_ACC_CONTROL); | ||
598 | u32 acc_control = nand_readreg(ctrl, offs); | ||
599 | u32 ecc_flags = ACC_CONTROL_WR_ECC | ACC_CONTROL_RD_ECC; | ||
600 | |||
601 | if (en) { | ||
602 | acc_control |= ecc_flags; /* enable RD/WR ECC */ | ||
603 | acc_control |= host->hwcfg.ecc_level | ||
604 | << NAND_ACC_CONTROL_ECC_SHIFT; | ||
605 | } else { | ||
606 | acc_control &= ~ecc_flags; /* disable RD/WR ECC */ | ||
607 | acc_control &= ~brcmnand_ecc_level_mask(ctrl); | ||
608 | } | ||
609 | |||
610 | nand_writereg(ctrl, offs, acc_control); | ||
611 | } | ||
612 | |||
613 | static inline int brcmnand_sector_1k_shift(struct brcmnand_controller *ctrl) | ||
614 | { | ||
615 | if (ctrl->nand_version >= 0x0600) | ||
616 | return 7; | ||
617 | else if (ctrl->nand_version >= 0x0500) | ||
618 | return 6; | ||
619 | else | ||
620 | return -1; | ||
621 | } | ||
622 | |||
623 | static int brcmnand_get_sector_size_1k(struct brcmnand_host *host) | ||
624 | { | ||
625 | struct brcmnand_controller *ctrl = host->ctrl; | ||
626 | int shift = brcmnand_sector_1k_shift(ctrl); | ||
627 | u16 acc_control_offs = brcmnand_cs_offset(ctrl, host->cs, | ||
628 | BRCMNAND_CS_ACC_CONTROL); | ||
629 | |||
630 | if (shift < 0) | ||
631 | return 0; | ||
632 | |||
633 | return (nand_readreg(ctrl, acc_control_offs) >> shift) & 0x1; | ||
634 | } | ||
635 | |||
636 | static void brcmnand_set_sector_size_1k(struct brcmnand_host *host, int val) | ||
637 | { | ||
638 | struct brcmnand_controller *ctrl = host->ctrl; | ||
639 | int shift = brcmnand_sector_1k_shift(ctrl); | ||
640 | u16 acc_control_offs = brcmnand_cs_offset(ctrl, host->cs, | ||
641 | BRCMNAND_CS_ACC_CONTROL); | ||
642 | u32 tmp; | ||
643 | |||
644 | if (shift < 0) | ||
645 | return; | ||
646 | |||
647 | tmp = nand_readreg(ctrl, acc_control_offs); | ||
648 | tmp &= ~(1 << shift); | ||
649 | tmp |= (!!val) << shift; | ||
650 | nand_writereg(ctrl, acc_control_offs, tmp); | ||
651 | } | ||
652 | |||
653 | /*********************************************************************** | ||
654 | * CS_NAND_SELECT | ||
655 | ***********************************************************************/ | ||
656 | |||
657 | enum { | ||
658 | CS_SELECT_NAND_WP = BIT(29), | ||
659 | CS_SELECT_AUTO_DEVICE_ID_CFG = BIT(30), | ||
660 | }; | ||
661 | |||
662 | static inline void brcmnand_set_wp(struct brcmnand_controller *ctrl, bool en) | ||
663 | { | ||
664 | u32 val = en ? CS_SELECT_NAND_WP : 0; | ||
665 | |||
666 | brcmnand_rmw_reg(ctrl, BRCMNAND_CS_SELECT, CS_SELECT_NAND_WP, 0, val); | ||
667 | } | ||
668 | |||
669 | /*********************************************************************** | ||
670 | * Flash DMA | ||
671 | ***********************************************************************/ | ||
672 | |||
673 | enum flash_dma_reg { | ||
674 | FLASH_DMA_REVISION = 0x00, | ||
675 | FLASH_DMA_FIRST_DESC = 0x04, | ||
676 | FLASH_DMA_FIRST_DESC_EXT = 0x08, | ||
677 | FLASH_DMA_CTRL = 0x0c, | ||
678 | FLASH_DMA_MODE = 0x10, | ||
679 | FLASH_DMA_STATUS = 0x14, | ||
680 | FLASH_DMA_INTERRUPT_DESC = 0x18, | ||
681 | FLASH_DMA_INTERRUPT_DESC_EXT = 0x1c, | ||
682 | FLASH_DMA_ERROR_STATUS = 0x20, | ||
683 | FLASH_DMA_CURRENT_DESC = 0x24, | ||
684 | FLASH_DMA_CURRENT_DESC_EXT = 0x28, | ||
685 | }; | ||
686 | |||
687 | static inline bool has_flash_dma(struct brcmnand_controller *ctrl) | ||
688 | { | ||
689 | return ctrl->flash_dma_base; | ||
690 | } | ||
691 | |||
692 | static inline bool flash_dma_buf_ok(const void *buf) | ||
693 | { | ||
694 | return buf && !is_vmalloc_addr(buf) && | ||
695 | likely(IS_ALIGNED((uintptr_t)buf, 4)); | ||
696 | } | ||
697 | |||
698 | static inline void flash_dma_writel(struct brcmnand_controller *ctrl, u8 offs, | ||
699 | u32 val) | ||
700 | { | ||
701 | brcmnand_writel(val, ctrl->flash_dma_base + offs); | ||
702 | } | ||
703 | |||
704 | static inline u32 flash_dma_readl(struct brcmnand_controller *ctrl, u8 offs) | ||
705 | { | ||
706 | return brcmnand_readl(ctrl->flash_dma_base + offs); | ||
707 | } | ||
708 | |||
709 | /* Low-level operation types: command, address, write, or read */ | ||
710 | enum brcmnand_llop_type { | ||
711 | LL_OP_CMD, | ||
712 | LL_OP_ADDR, | ||
713 | LL_OP_WR, | ||
714 | LL_OP_RD, | ||
715 | }; | ||
716 | |||
717 | /*********************************************************************** | ||
718 | * Internal support functions | ||
719 | ***********************************************************************/ | ||
720 | |||
721 | static inline bool is_hamming_ecc(struct brcmnand_cfg *cfg) | ||
722 | { | ||
723 | return cfg->sector_size_1k == 0 && cfg->spare_area_size == 16 && | ||
724 | cfg->ecc_level == 15; | ||
725 | } | ||
726 | |||
727 | /* | ||
728 | * Returns a nand_ecclayout strucutre for the given layout/configuration. | ||
729 | * Returns NULL on failure. | ||
730 | */ | ||
731 | static struct nand_ecclayout *brcmnand_create_layout(int ecc_level, | ||
732 | struct brcmnand_host *host) | ||
733 | { | ||
734 | struct brcmnand_cfg *cfg = &host->hwcfg; | ||
735 | int i, j; | ||
736 | struct nand_ecclayout *layout; | ||
737 | int req; | ||
738 | int sectors; | ||
739 | int sas; | ||
740 | int idx1, idx2; | ||
741 | |||
742 | layout = devm_kzalloc(&host->pdev->dev, sizeof(*layout), GFP_KERNEL); | ||
743 | if (!layout) | ||
744 | return NULL; | ||
745 | |||
746 | sectors = cfg->page_size / (512 << cfg->sector_size_1k); | ||
747 | sas = cfg->spare_area_size << cfg->sector_size_1k; | ||
748 | |||
749 | /* Hamming */ | ||
750 | if (is_hamming_ecc(cfg)) { | ||
751 | for (i = 0, idx1 = 0, idx2 = 0; i < sectors; i++) { | ||
752 | /* First sector of each page may have BBI */ | ||
753 | if (i == 0) { | ||
754 | layout->oobfree[idx2].offset = i * sas + 1; | ||
755 | /* Small-page NAND use byte 6 for BBI */ | ||
756 | if (cfg->page_size == 512) | ||
757 | layout->oobfree[idx2].offset--; | ||
758 | layout->oobfree[idx2].length = 5; | ||
759 | } else { | ||
760 | layout->oobfree[idx2].offset = i * sas; | ||
761 | layout->oobfree[idx2].length = 6; | ||
762 | } | ||
763 | idx2++; | ||
764 | layout->eccpos[idx1++] = i * sas + 6; | ||
765 | layout->eccpos[idx1++] = i * sas + 7; | ||
766 | layout->eccpos[idx1++] = i * sas + 8; | ||
767 | layout->oobfree[idx2].offset = i * sas + 9; | ||
768 | layout->oobfree[idx2].length = 7; | ||
769 | idx2++; | ||
770 | /* Leave zero-terminated entry for OOBFREE */ | ||
771 | if (idx1 >= MTD_MAX_ECCPOS_ENTRIES_LARGE || | ||
772 | idx2 >= MTD_MAX_OOBFREE_ENTRIES_LARGE - 1) | ||
773 | break; | ||
774 | } | ||
775 | goto out; | ||
776 | } | ||
777 | |||
778 | /* | ||
779 | * CONTROLLER_VERSION: | ||
780 | * < v5.0: ECC_REQ = ceil(BCH_T * 13/8) | ||
781 | * >= v5.0: ECC_REQ = ceil(BCH_T * 14/8) | ||
782 | * But we will just be conservative. | ||
783 | */ | ||
784 | req = DIV_ROUND_UP(ecc_level * 14, 8); | ||
785 | if (req >= sas) { | ||
786 | dev_err(&host->pdev->dev, | ||
787 | "error: ECC too large for OOB (ECC bytes %d, spare sector %d)\n", | ||
788 | req, sas); | ||
789 | return NULL; | ||
790 | } | ||
791 | |||
792 | layout->eccbytes = req * sectors; | ||
793 | for (i = 0, idx1 = 0, idx2 = 0; i < sectors; i++) { | ||
794 | for (j = sas - req; j < sas && idx1 < | ||
795 | MTD_MAX_ECCPOS_ENTRIES_LARGE; j++, idx1++) | ||
796 | layout->eccpos[idx1] = i * sas + j; | ||
797 | |||
798 | /* First sector of each page may have BBI */ | ||
799 | if (i == 0) { | ||
800 | if (cfg->page_size == 512 && (sas - req >= 6)) { | ||
801 | /* Small-page NAND use byte 6 for BBI */ | ||
802 | layout->oobfree[idx2].offset = 0; | ||
803 | layout->oobfree[idx2].length = 5; | ||
804 | idx2++; | ||
805 | if (sas - req > 6) { | ||
806 | layout->oobfree[idx2].offset = 6; | ||
807 | layout->oobfree[idx2].length = | ||
808 | sas - req - 6; | ||
809 | idx2++; | ||
810 | } | ||
811 | } else if (sas > req + 1) { | ||
812 | layout->oobfree[idx2].offset = i * sas + 1; | ||
813 | layout->oobfree[idx2].length = sas - req - 1; | ||
814 | idx2++; | ||
815 | } | ||
816 | } else if (sas > req) { | ||
817 | layout->oobfree[idx2].offset = i * sas; | ||
818 | layout->oobfree[idx2].length = sas - req; | ||
819 | idx2++; | ||
820 | } | ||
821 | /* Leave zero-terminated entry for OOBFREE */ | ||
822 | if (idx1 >= MTD_MAX_ECCPOS_ENTRIES_LARGE || | ||
823 | idx2 >= MTD_MAX_OOBFREE_ENTRIES_LARGE - 1) | ||
824 | break; | ||
825 | } | ||
826 | out: | ||
827 | /* Sum available OOB */ | ||
828 | for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES_LARGE; i++) | ||
829 | layout->oobavail += layout->oobfree[i].length; | ||
830 | return layout; | ||
831 | } | ||
832 | |||
833 | static struct nand_ecclayout *brcmstb_choose_ecc_layout( | ||
834 | struct brcmnand_host *host) | ||
835 | { | ||
836 | struct nand_ecclayout *layout; | ||
837 | struct brcmnand_cfg *p = &host->hwcfg; | ||
838 | unsigned int ecc_level = p->ecc_level; | ||
839 | |||
840 | if (p->sector_size_1k) | ||
841 | ecc_level <<= 1; | ||
842 | |||
843 | layout = brcmnand_create_layout(ecc_level, host); | ||
844 | if (!layout) { | ||
845 | dev_err(&host->pdev->dev, | ||
846 | "no proper ecc_layout for this NAND cfg\n"); | ||
847 | return NULL; | ||
848 | } | ||
849 | |||
850 | return layout; | ||
851 | } | ||
852 | |||
853 | static void brcmnand_wp(struct mtd_info *mtd, int wp) | ||
854 | { | ||
855 | struct nand_chip *chip = mtd->priv; | ||
856 | struct brcmnand_host *host = chip->priv; | ||
857 | struct brcmnand_controller *ctrl = host->ctrl; | ||
858 | |||
859 | if ((ctrl->features & BRCMNAND_HAS_WP) && wp_on == 1) { | ||
860 | static int old_wp = -1; | ||
861 | |||
862 | if (old_wp != wp) { | ||
863 | dev_dbg(ctrl->dev, "WP %s\n", wp ? "on" : "off"); | ||
864 | old_wp = wp; | ||
865 | } | ||
866 | brcmnand_set_wp(ctrl, wp); | ||
867 | } | ||
868 | } | ||
869 | |||
870 | /* Helper functions for reading and writing OOB registers */ | ||
871 | static inline u8 oob_reg_read(struct brcmnand_controller *ctrl, u32 offs) | ||
872 | { | ||
873 | u16 offset0, offset10, reg_offs; | ||
874 | |||
875 | offset0 = ctrl->reg_offsets[BRCMNAND_OOB_READ_BASE]; | ||
876 | offset10 = ctrl->reg_offsets[BRCMNAND_OOB_READ_10_BASE]; | ||
877 | |||
878 | if (offs >= ctrl->max_oob) | ||
879 | return 0x77; | ||
880 | |||
881 | if (offs >= 16 && offset10) | ||
882 | reg_offs = offset10 + ((offs - 0x10) & ~0x03); | ||
883 | else | ||
884 | reg_offs = offset0 + (offs & ~0x03); | ||
885 | |||
886 | return nand_readreg(ctrl, reg_offs) >> (24 - ((offs & 0x03) << 3)); | ||
887 | } | ||
888 | |||
889 | static inline void oob_reg_write(struct brcmnand_controller *ctrl, u32 offs, | ||
890 | u32 data) | ||
891 | { | ||
892 | u16 offset0, offset10, reg_offs; | ||
893 | |||
894 | offset0 = ctrl->reg_offsets[BRCMNAND_OOB_WRITE_BASE]; | ||
895 | offset10 = ctrl->reg_offsets[BRCMNAND_OOB_WRITE_10_BASE]; | ||
896 | |||
897 | if (offs >= ctrl->max_oob) | ||
898 | return; | ||
899 | |||
900 | if (offs >= 16 && offset10) | ||
901 | reg_offs = offset10 + ((offs - 0x10) & ~0x03); | ||
902 | else | ||
903 | reg_offs = offset0 + (offs & ~0x03); | ||
904 | |||
905 | nand_writereg(ctrl, reg_offs, data); | ||
906 | } | ||
907 | |||
908 | /* | ||
909 | * read_oob_from_regs - read data from OOB registers | ||
910 | * @ctrl: NAND controller | ||
911 | * @i: sub-page sector index | ||
912 | * @oob: buffer to read to | ||
913 | * @sas: spare area sector size (i.e., OOB size per FLASH_CACHE) | ||
914 | * @sector_1k: 1 for 1KiB sectors, 0 for 512B, other values are illegal | ||
915 | */ | ||
916 | static int read_oob_from_regs(struct brcmnand_controller *ctrl, int i, u8 *oob, | ||
917 | int sas, int sector_1k) | ||
918 | { | ||
919 | int tbytes = sas << sector_1k; | ||
920 | int j; | ||
921 | |||
922 | /* Adjust OOB values for 1K sector size */ | ||
923 | if (sector_1k && (i & 0x01)) | ||
924 | tbytes = max(0, tbytes - (int)ctrl->max_oob); | ||
925 | tbytes = min_t(int, tbytes, ctrl->max_oob); | ||
926 | |||
927 | for (j = 0; j < tbytes; j++) | ||
928 | oob[j] = oob_reg_read(ctrl, j); | ||
929 | return tbytes; | ||
930 | } | ||
931 | |||
932 | /* | ||
933 | * write_oob_to_regs - write data to OOB registers | ||
934 | * @i: sub-page sector index | ||
935 | * @oob: buffer to write from | ||
936 | * @sas: spare area sector size (i.e., OOB size per FLASH_CACHE) | ||
937 | * @sector_1k: 1 for 1KiB sectors, 0 for 512B, other values are illegal | ||
938 | */ | ||
939 | static int write_oob_to_regs(struct brcmnand_controller *ctrl, int i, | ||
940 | const u8 *oob, int sas, int sector_1k) | ||
941 | { | ||
942 | int tbytes = sas << sector_1k; | ||
943 | int j; | ||
944 | |||
945 | /* Adjust OOB values for 1K sector size */ | ||
946 | if (sector_1k && (i & 0x01)) | ||
947 | tbytes = max(0, tbytes - (int)ctrl->max_oob); | ||
948 | tbytes = min_t(int, tbytes, ctrl->max_oob); | ||
949 | |||
950 | for (j = 0; j < tbytes; j += 4) | ||
951 | oob_reg_write(ctrl, j, | ||
952 | (oob[j + 0] << 24) | | ||
953 | (oob[j + 1] << 16) | | ||
954 | (oob[j + 2] << 8) | | ||
955 | (oob[j + 3] << 0)); | ||
956 | return tbytes; | ||
957 | } | ||
958 | |||
959 | static irqreturn_t brcmnand_ctlrdy_irq(int irq, void *data) | ||
960 | { | ||
961 | struct brcmnand_controller *ctrl = data; | ||
962 | |||
963 | /* Discard all NAND_CTLRDY interrupts during DMA */ | ||
964 | if (ctrl->dma_pending) | ||
965 | return IRQ_HANDLED; | ||
966 | |||
967 | complete(&ctrl->done); | ||
968 | return IRQ_HANDLED; | ||
969 | } | ||
970 | |||
971 | /* Handle SoC-specific interrupt hardware */ | ||
972 | static irqreturn_t brcmnand_irq(int irq, void *data) | ||
973 | { | ||
974 | struct brcmnand_controller *ctrl = data; | ||
975 | |||
976 | if (ctrl->soc->ctlrdy_ack(ctrl->soc)) | ||
977 | return brcmnand_ctlrdy_irq(irq, data); | ||
978 | |||
979 | return IRQ_NONE; | ||
980 | } | ||
981 | |||
982 | static irqreturn_t brcmnand_dma_irq(int irq, void *data) | ||
983 | { | ||
984 | struct brcmnand_controller *ctrl = data; | ||
985 | |||
986 | complete(&ctrl->dma_done); | ||
987 | |||
988 | return IRQ_HANDLED; | ||
989 | } | ||
990 | |||
991 | static void brcmnand_send_cmd(struct brcmnand_host *host, int cmd) | ||
992 | { | ||
993 | struct brcmnand_controller *ctrl = host->ctrl; | ||
994 | u32 intfc; | ||
995 | |||
996 | dev_dbg(ctrl->dev, "send native cmd %d addr_lo 0x%x\n", cmd, | ||
997 | brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS)); | ||
998 | BUG_ON(ctrl->cmd_pending != 0); | ||
999 | ctrl->cmd_pending = cmd; | ||
1000 | |||
1001 | intfc = brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS); | ||
1002 | BUG_ON(!(intfc & INTFC_CTLR_READY)); | ||
1003 | |||
1004 | mb(); /* flush previous writes */ | ||
1005 | brcmnand_write_reg(ctrl, BRCMNAND_CMD_START, | ||
1006 | cmd << brcmnand_cmd_shift(ctrl)); | ||
1007 | } | ||
1008 | |||
1009 | /*********************************************************************** | ||
1010 | * NAND MTD API: read/program/erase | ||
1011 | ***********************************************************************/ | ||
1012 | |||
1013 | static void brcmnand_cmd_ctrl(struct mtd_info *mtd, int dat, | ||
1014 | unsigned int ctrl) | ||
1015 | { | ||
1016 | /* intentionally left blank */ | ||
1017 | } | ||
1018 | |||
1019 | static int brcmnand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) | ||
1020 | { | ||
1021 | struct nand_chip *chip = mtd->priv; | ||
1022 | struct brcmnand_host *host = chip->priv; | ||
1023 | struct brcmnand_controller *ctrl = host->ctrl; | ||
1024 | unsigned long timeo = msecs_to_jiffies(100); | ||
1025 | |||
1026 | dev_dbg(ctrl->dev, "wait on native cmd %d\n", ctrl->cmd_pending); | ||
1027 | if (ctrl->cmd_pending && | ||
1028 | wait_for_completion_timeout(&ctrl->done, timeo) <= 0) { | ||
1029 | u32 cmd = brcmnand_read_reg(ctrl, BRCMNAND_CMD_START) | ||
1030 | >> brcmnand_cmd_shift(ctrl); | ||
1031 | |||
1032 | dev_err_ratelimited(ctrl->dev, | ||
1033 | "timeout waiting for command %#02x\n", cmd); | ||
1034 | dev_err_ratelimited(ctrl->dev, "intfc status %08x\n", | ||
1035 | brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS)); | ||
1036 | } | ||
1037 | ctrl->cmd_pending = 0; | ||
1038 | return brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS) & | ||
1039 | INTFC_FLASH_STATUS; | ||
1040 | } | ||
1041 | |||
1042 | enum { | ||
1043 | LLOP_RE = BIT(16), | ||
1044 | LLOP_WE = BIT(17), | ||
1045 | LLOP_ALE = BIT(18), | ||
1046 | LLOP_CLE = BIT(19), | ||
1047 | LLOP_RETURN_IDLE = BIT(31), | ||
1048 | |||
1049 | LLOP_DATA_MASK = GENMASK(15, 0), | ||
1050 | }; | ||
1051 | |||
1052 | static int brcmnand_low_level_op(struct brcmnand_host *host, | ||
1053 | enum brcmnand_llop_type type, u32 data, | ||
1054 | bool last_op) | ||
1055 | { | ||
1056 | struct mtd_info *mtd = &host->mtd; | ||
1057 | struct nand_chip *chip = &host->chip; | ||
1058 | struct brcmnand_controller *ctrl = host->ctrl; | ||
1059 | u32 tmp; | ||
1060 | |||
1061 | tmp = data & LLOP_DATA_MASK; | ||
1062 | switch (type) { | ||
1063 | case LL_OP_CMD: | ||
1064 | tmp |= LLOP_WE | LLOP_CLE; | ||
1065 | break; | ||
1066 | case LL_OP_ADDR: | ||
1067 | /* WE | ALE */ | ||
1068 | tmp |= LLOP_WE | LLOP_ALE; | ||
1069 | break; | ||
1070 | case LL_OP_WR: | ||
1071 | /* WE */ | ||
1072 | tmp |= LLOP_WE; | ||
1073 | break; | ||
1074 | case LL_OP_RD: | ||
1075 | /* RE */ | ||
1076 | tmp |= LLOP_RE; | ||
1077 | break; | ||
1078 | } | ||
1079 | if (last_op) | ||
1080 | /* RETURN_IDLE */ | ||
1081 | tmp |= LLOP_RETURN_IDLE; | ||
1082 | |||
1083 | dev_dbg(ctrl->dev, "ll_op cmd %#x\n", tmp); | ||
1084 | |||
1085 | brcmnand_write_reg(ctrl, BRCMNAND_LL_OP, tmp); | ||
1086 | (void)brcmnand_read_reg(ctrl, BRCMNAND_LL_OP); | ||
1087 | |||
1088 | brcmnand_send_cmd(host, CMD_LOW_LEVEL_OP); | ||
1089 | return brcmnand_waitfunc(mtd, chip); | ||
1090 | } | ||
1091 | |||
1092 | static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command, | ||
1093 | int column, int page_addr) | ||
1094 | { | ||
1095 | struct nand_chip *chip = mtd->priv; | ||
1096 | struct brcmnand_host *host = chip->priv; | ||
1097 | struct brcmnand_controller *ctrl = host->ctrl; | ||
1098 | u64 addr = (u64)page_addr << chip->page_shift; | ||
1099 | int native_cmd = 0; | ||
1100 | |||
1101 | if (command == NAND_CMD_READID || command == NAND_CMD_PARAM || | ||
1102 | command == NAND_CMD_RNDOUT) | ||
1103 | addr = (u64)column; | ||
1104 | /* Avoid propagating a negative, don't-care address */ | ||
1105 | else if (page_addr < 0) | ||
1106 | addr = 0; | ||
1107 | |||
1108 | dev_dbg(ctrl->dev, "cmd 0x%x addr 0x%llx\n", command, | ||
1109 | (unsigned long long)addr); | ||
1110 | |||
1111 | host->last_cmd = command; | ||
1112 | host->last_byte = 0; | ||
1113 | host->last_addr = addr; | ||
1114 | |||
1115 | switch (command) { | ||
1116 | case NAND_CMD_RESET: | ||
1117 | native_cmd = CMD_FLASH_RESET; | ||
1118 | break; | ||
1119 | case NAND_CMD_STATUS: | ||
1120 | native_cmd = CMD_STATUS_READ; | ||
1121 | break; | ||
1122 | case NAND_CMD_READID: | ||
1123 | native_cmd = CMD_DEVICE_ID_READ; | ||
1124 | break; | ||
1125 | case NAND_CMD_READOOB: | ||
1126 | native_cmd = CMD_SPARE_AREA_READ; | ||
1127 | break; | ||
1128 | case NAND_CMD_ERASE1: | ||
1129 | native_cmd = CMD_BLOCK_ERASE; | ||
1130 | brcmnand_wp(mtd, 0); | ||
1131 | break; | ||
1132 | case NAND_CMD_PARAM: | ||
1133 | native_cmd = CMD_PARAMETER_READ; | ||
1134 | break; | ||
1135 | case NAND_CMD_SET_FEATURES: | ||
1136 | case NAND_CMD_GET_FEATURES: | ||
1137 | brcmnand_low_level_op(host, LL_OP_CMD, command, false); | ||
1138 | brcmnand_low_level_op(host, LL_OP_ADDR, column, false); | ||
1139 | break; | ||
1140 | case NAND_CMD_RNDOUT: | ||
1141 | native_cmd = CMD_PARAMETER_CHANGE_COL; | ||
1142 | addr &= ~((u64)(FC_BYTES - 1)); | ||
1143 | /* | ||
1144 | * HW quirk: PARAMETER_CHANGE_COL requires SECTOR_SIZE_1K=0 | ||
1145 | * NB: hwcfg.sector_size_1k may not be initialized yet | ||
1146 | */ | ||
1147 | if (brcmnand_get_sector_size_1k(host)) { | ||
1148 | host->hwcfg.sector_size_1k = | ||
1149 | brcmnand_get_sector_size_1k(host); | ||
1150 | brcmnand_set_sector_size_1k(host, 0); | ||
1151 | } | ||
1152 | break; | ||
1153 | } | ||
1154 | |||
1155 | if (!native_cmd) | ||
1156 | return; | ||
1157 | |||
1158 | brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS, | ||
1159 | (host->cs << 16) | ((addr >> 32) & 0xffff)); | ||
1160 | (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS); | ||
1161 | brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS, lower_32_bits(addr)); | ||
1162 | (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS); | ||
1163 | |||
1164 | brcmnand_send_cmd(host, native_cmd); | ||
1165 | brcmnand_waitfunc(mtd, chip); | ||
1166 | |||
1167 | if (native_cmd == CMD_PARAMETER_READ || | ||
1168 | native_cmd == CMD_PARAMETER_CHANGE_COL) { | ||
1169 | int i; | ||
1170 | |||
1171 | brcmnand_soc_data_bus_prepare(ctrl->soc); | ||
1172 | |||
1173 | /* | ||
1174 | * Must cache the FLASH_CACHE now, since changes in | ||
1175 | * SECTOR_SIZE_1K may invalidate it | ||
1176 | */ | ||
1177 | for (i = 0; i < FC_WORDS; i++) | ||
1178 | ctrl->flash_cache[i] = brcmnand_read_fc(ctrl, i); | ||
1179 | |||
1180 | brcmnand_soc_data_bus_unprepare(ctrl->soc); | ||
1181 | |||
1182 | /* Cleanup from HW quirk: restore SECTOR_SIZE_1K */ | ||
1183 | if (host->hwcfg.sector_size_1k) | ||
1184 | brcmnand_set_sector_size_1k(host, | ||
1185 | host->hwcfg.sector_size_1k); | ||
1186 | } | ||
1187 | |||
1188 | /* Re-enable protection is necessary only after erase */ | ||
1189 | if (command == NAND_CMD_ERASE1) | ||
1190 | brcmnand_wp(mtd, 1); | ||
1191 | } | ||
1192 | |||
1193 | static uint8_t brcmnand_read_byte(struct mtd_info *mtd) | ||
1194 | { | ||
1195 | struct nand_chip *chip = mtd->priv; | ||
1196 | struct brcmnand_host *host = chip->priv; | ||
1197 | struct brcmnand_controller *ctrl = host->ctrl; | ||
1198 | uint8_t ret = 0; | ||
1199 | int addr, offs; | ||
1200 | |||
1201 | switch (host->last_cmd) { | ||
1202 | case NAND_CMD_READID: | ||
1203 | if (host->last_byte < 4) | ||
1204 | ret = brcmnand_read_reg(ctrl, BRCMNAND_ID) >> | ||
1205 | (24 - (host->last_byte << 3)); | ||
1206 | else if (host->last_byte < 8) | ||
1207 | ret = brcmnand_read_reg(ctrl, BRCMNAND_ID_EXT) >> | ||
1208 | (56 - (host->last_byte << 3)); | ||
1209 | break; | ||
1210 | |||
1211 | case NAND_CMD_READOOB: | ||
1212 | ret = oob_reg_read(ctrl, host->last_byte); | ||
1213 | break; | ||
1214 | |||
1215 | case NAND_CMD_STATUS: | ||
1216 | ret = brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS) & | ||
1217 | INTFC_FLASH_STATUS; | ||
1218 | if (wp_on) /* hide WP status */ | ||
1219 | ret |= NAND_STATUS_WP; | ||
1220 | break; | ||
1221 | |||
1222 | case NAND_CMD_PARAM: | ||
1223 | case NAND_CMD_RNDOUT: | ||
1224 | addr = host->last_addr + host->last_byte; | ||
1225 | offs = addr & (FC_BYTES - 1); | ||
1226 | |||
1227 | /* At FC_BYTES boundary, switch to next column */ | ||
1228 | if (host->last_byte > 0 && offs == 0) | ||
1229 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, addr, -1); | ||
1230 | |||
1231 | ret = ctrl->flash_cache[offs >> 2] >> | ||
1232 | (24 - ((offs & 0x03) << 3)); | ||
1233 | break; | ||
1234 | case NAND_CMD_GET_FEATURES: | ||
1235 | if (host->last_byte >= ONFI_SUBFEATURE_PARAM_LEN) { | ||
1236 | ret = 0; | ||
1237 | } else { | ||
1238 | bool last = host->last_byte == | ||
1239 | ONFI_SUBFEATURE_PARAM_LEN - 1; | ||
1240 | brcmnand_low_level_op(host, LL_OP_RD, 0, last); | ||
1241 | ret = brcmnand_read_reg(ctrl, BRCMNAND_LL_RDATA) & 0xff; | ||
1242 | } | ||
1243 | } | ||
1244 | |||
1245 | dev_dbg(ctrl->dev, "read byte = 0x%02x\n", ret); | ||
1246 | host->last_byte++; | ||
1247 | |||
1248 | return ret; | ||
1249 | } | ||
1250 | |||
1251 | static void brcmnand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | ||
1252 | { | ||
1253 | int i; | ||
1254 | |||
1255 | for (i = 0; i < len; i++, buf++) | ||
1256 | *buf = brcmnand_read_byte(mtd); | ||
1257 | } | ||
1258 | |||
1259 | static void brcmnand_write_buf(struct mtd_info *mtd, const uint8_t *buf, | ||
1260 | int len) | ||
1261 | { | ||
1262 | int i; | ||
1263 | struct nand_chip *chip = mtd->priv; | ||
1264 | struct brcmnand_host *host = chip->priv; | ||
1265 | |||
1266 | switch (host->last_cmd) { | ||
1267 | case NAND_CMD_SET_FEATURES: | ||
1268 | for (i = 0; i < len; i++) | ||
1269 | brcmnand_low_level_op(host, LL_OP_WR, buf[i], | ||
1270 | (i + 1) == len); | ||
1271 | break; | ||
1272 | default: | ||
1273 | BUG(); | ||
1274 | break; | ||
1275 | } | ||
1276 | } | ||
1277 | |||
1278 | /** | ||
1279 | * Construct a FLASH_DMA descriptor as part of a linked list. You must know the | ||
1280 | * following ahead of time: | ||
1281 | * - Is this descriptor the beginning or end of a linked list? | ||
1282 | * - What is the (DMA) address of the next descriptor in the linked list? | ||
1283 | */ | ||
1284 | static int brcmnand_fill_dma_desc(struct brcmnand_host *host, | ||
1285 | struct brcm_nand_dma_desc *desc, u64 addr, | ||
1286 | dma_addr_t buf, u32 len, u8 dma_cmd, | ||
1287 | bool begin, bool end, | ||
1288 | dma_addr_t next_desc) | ||
1289 | { | ||
1290 | memset(desc, 0, sizeof(*desc)); | ||
1291 | /* Descriptors are written in native byte order (wordwise) */ | ||
1292 | desc->next_desc = lower_32_bits(next_desc); | ||
1293 | desc->next_desc_ext = upper_32_bits(next_desc); | ||
1294 | desc->cmd_irq = (dma_cmd << 24) | | ||
1295 | (end ? (0x03 << 8) : 0) | /* IRQ | STOP */ | ||
1296 | (!!begin) | ((!!end) << 1); /* head, tail */ | ||
1297 | #ifdef CONFIG_CPU_BIG_ENDIAN | ||
1298 | desc->cmd_irq |= 0x01 << 12; | ||
1299 | #endif | ||
1300 | desc->dram_addr = lower_32_bits(buf); | ||
1301 | desc->dram_addr_ext = upper_32_bits(buf); | ||
1302 | desc->tfr_len = len; | ||
1303 | desc->total_len = len; | ||
1304 | desc->flash_addr = lower_32_bits(addr); | ||
1305 | desc->flash_addr_ext = upper_32_bits(addr); | ||
1306 | desc->cs = host->cs; | ||
1307 | desc->status_valid = 0x01; | ||
1308 | return 0; | ||
1309 | } | ||
1310 | |||
1311 | /** | ||
1312 | * Kick the FLASH_DMA engine, with a given DMA descriptor | ||
1313 | */ | ||
1314 | static void brcmnand_dma_run(struct brcmnand_host *host, dma_addr_t desc) | ||
1315 | { | ||
1316 | struct brcmnand_controller *ctrl = host->ctrl; | ||
1317 | unsigned long timeo = msecs_to_jiffies(100); | ||
1318 | |||
1319 | flash_dma_writel(ctrl, FLASH_DMA_FIRST_DESC, lower_32_bits(desc)); | ||
1320 | (void)flash_dma_readl(ctrl, FLASH_DMA_FIRST_DESC); | ||
1321 | flash_dma_writel(ctrl, FLASH_DMA_FIRST_DESC_EXT, upper_32_bits(desc)); | ||
1322 | (void)flash_dma_readl(ctrl, FLASH_DMA_FIRST_DESC_EXT); | ||
1323 | |||
1324 | /* Start FLASH_DMA engine */ | ||
1325 | ctrl->dma_pending = true; | ||
1326 | mb(); /* flush previous writes */ | ||
1327 | flash_dma_writel(ctrl, FLASH_DMA_CTRL, 0x03); /* wake | run */ | ||
1328 | |||
1329 | if (wait_for_completion_timeout(&ctrl->dma_done, timeo) <= 0) { | ||
1330 | dev_err(ctrl->dev, | ||
1331 | "timeout waiting for DMA; status %#x, error status %#x\n", | ||
1332 | flash_dma_readl(ctrl, FLASH_DMA_STATUS), | ||
1333 | flash_dma_readl(ctrl, FLASH_DMA_ERROR_STATUS)); | ||
1334 | } | ||
1335 | ctrl->dma_pending = false; | ||
1336 | flash_dma_writel(ctrl, FLASH_DMA_CTRL, 0); /* force stop */ | ||
1337 | } | ||
1338 | |||
1339 | static int brcmnand_dma_trans(struct brcmnand_host *host, u64 addr, u32 *buf, | ||
1340 | u32 len, u8 dma_cmd) | ||
1341 | { | ||
1342 | struct brcmnand_controller *ctrl = host->ctrl; | ||
1343 | dma_addr_t buf_pa; | ||
1344 | int dir = dma_cmd == CMD_PAGE_READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
1345 | |||
1346 | buf_pa = dma_map_single(ctrl->dev, buf, len, dir); | ||
1347 | if (dma_mapping_error(ctrl->dev, buf_pa)) { | ||
1348 | dev_err(ctrl->dev, "unable to map buffer for DMA\n"); | ||
1349 | return -ENOMEM; | ||
1350 | } | ||
1351 | |||
1352 | brcmnand_fill_dma_desc(host, ctrl->dma_desc, addr, buf_pa, len, | ||
1353 | dma_cmd, true, true, 0); | ||
1354 | |||
1355 | brcmnand_dma_run(host, ctrl->dma_pa); | ||
1356 | |||
1357 | dma_unmap_single(ctrl->dev, buf_pa, len, dir); | ||
1358 | |||
1359 | if (ctrl->dma_desc->status_valid & FLASH_DMA_ECC_ERROR) | ||
1360 | return -EBADMSG; | ||
1361 | else if (ctrl->dma_desc->status_valid & FLASH_DMA_CORR_ERROR) | ||
1362 | return -EUCLEAN; | ||
1363 | |||
1364 | return 0; | ||
1365 | } | ||
1366 | |||
1367 | /* | ||
1368 | * Assumes proper CS is already set | ||
1369 | */ | ||
1370 | static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip, | ||
1371 | u64 addr, unsigned int trans, u32 *buf, | ||
1372 | u8 *oob, u64 *err_addr) | ||
1373 | { | ||
1374 | struct brcmnand_host *host = chip->priv; | ||
1375 | struct brcmnand_controller *ctrl = host->ctrl; | ||
1376 | int i, j, ret = 0; | ||
1377 | |||
1378 | /* Clear error addresses */ | ||
1379 | brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_ADDR, 0); | ||
1380 | brcmnand_write_reg(ctrl, BRCMNAND_CORR_ADDR, 0); | ||
1381 | |||
1382 | brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS, | ||
1383 | (host->cs << 16) | ((addr >> 32) & 0xffff)); | ||
1384 | (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS); | ||
1385 | |||
1386 | for (i = 0; i < trans; i++, addr += FC_BYTES) { | ||
1387 | brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS, | ||
1388 | lower_32_bits(addr)); | ||
1389 | (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS); | ||
1390 | /* SPARE_AREA_READ does not use ECC, so just use PAGE_READ */ | ||
1391 | brcmnand_send_cmd(host, CMD_PAGE_READ); | ||
1392 | brcmnand_waitfunc(mtd, chip); | ||
1393 | |||
1394 | if (likely(buf)) { | ||
1395 | brcmnand_soc_data_bus_prepare(ctrl->soc); | ||
1396 | |||
1397 | for (j = 0; j < FC_WORDS; j++, buf++) | ||
1398 | *buf = brcmnand_read_fc(ctrl, j); | ||
1399 | |||
1400 | brcmnand_soc_data_bus_unprepare(ctrl->soc); | ||
1401 | } | ||
1402 | |||
1403 | if (oob) | ||
1404 | oob += read_oob_from_regs(ctrl, i, oob, | ||
1405 | mtd->oobsize / trans, | ||
1406 | host->hwcfg.sector_size_1k); | ||
1407 | |||
1408 | if (!ret) { | ||
1409 | *err_addr = brcmnand_read_reg(ctrl, | ||
1410 | BRCMNAND_UNCORR_ADDR) | | ||
1411 | ((u64)(brcmnand_read_reg(ctrl, | ||
1412 | BRCMNAND_UNCORR_EXT_ADDR) | ||
1413 | & 0xffff) << 32); | ||
1414 | if (*err_addr) | ||
1415 | ret = -EBADMSG; | ||
1416 | } | ||
1417 | |||
1418 | if (!ret) { | ||
1419 | *err_addr = brcmnand_read_reg(ctrl, | ||
1420 | BRCMNAND_CORR_ADDR) | | ||
1421 | ((u64)(brcmnand_read_reg(ctrl, | ||
1422 | BRCMNAND_CORR_EXT_ADDR) | ||
1423 | & 0xffff) << 32); | ||
1424 | if (*err_addr) | ||
1425 | ret = -EUCLEAN; | ||
1426 | } | ||
1427 | } | ||
1428 | |||
1429 | return ret; | ||
1430 | } | ||
1431 | |||
1432 | static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip, | ||
1433 | u64 addr, unsigned int trans, u32 *buf, u8 *oob) | ||
1434 | { | ||
1435 | struct brcmnand_host *host = chip->priv; | ||
1436 | struct brcmnand_controller *ctrl = host->ctrl; | ||
1437 | u64 err_addr = 0; | ||
1438 | int err; | ||
1439 | |||
1440 | dev_dbg(ctrl->dev, "read %llx -> %p\n", (unsigned long long)addr, buf); | ||
1441 | |||
1442 | brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_COUNT, 0); | ||
1443 | |||
1444 | if (has_flash_dma(ctrl) && !oob && flash_dma_buf_ok(buf)) { | ||
1445 | err = brcmnand_dma_trans(host, addr, buf, trans * FC_BYTES, | ||
1446 | CMD_PAGE_READ); | ||
1447 | if (err) { | ||
1448 | if (mtd_is_bitflip_or_eccerr(err)) | ||
1449 | err_addr = addr; | ||
1450 | else | ||
1451 | return -EIO; | ||
1452 | } | ||
1453 | } else { | ||
1454 | if (oob) | ||
1455 | memset(oob, 0x99, mtd->oobsize); | ||
1456 | |||
1457 | err = brcmnand_read_by_pio(mtd, chip, addr, trans, buf, | ||
1458 | oob, &err_addr); | ||
1459 | } | ||
1460 | |||
1461 | if (mtd_is_eccerr(err)) { | ||
1462 | dev_dbg(ctrl->dev, "uncorrectable error at 0x%llx\n", | ||
1463 | (unsigned long long)err_addr); | ||
1464 | mtd->ecc_stats.failed++; | ||
1465 | /* NAND layer expects zero on ECC errors */ | ||
1466 | return 0; | ||
1467 | } | ||
1468 | |||
1469 | if (mtd_is_bitflip(err)) { | ||
1470 | unsigned int corrected = brcmnand_count_corrected(ctrl); | ||
1471 | |||
1472 | dev_dbg(ctrl->dev, "corrected error at 0x%llx\n", | ||
1473 | (unsigned long long)err_addr); | ||
1474 | mtd->ecc_stats.corrected += corrected; | ||
1475 | /* Always exceed the software-imposed threshold */ | ||
1476 | return max(mtd->bitflip_threshold, corrected); | ||
1477 | } | ||
1478 | |||
1479 | return 0; | ||
1480 | } | ||
1481 | |||
1482 | static int brcmnand_read_page(struct mtd_info *mtd, struct nand_chip *chip, | ||
1483 | uint8_t *buf, int oob_required, int page) | ||
1484 | { | ||
1485 | struct brcmnand_host *host = chip->priv; | ||
1486 | u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL; | ||
1487 | |||
1488 | return brcmnand_read(mtd, chip, host->last_addr, | ||
1489 | mtd->writesize >> FC_SHIFT, (u32 *)buf, oob); | ||
1490 | } | ||
1491 | |||
1492 | static int brcmnand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | ||
1493 | uint8_t *buf, int oob_required, int page) | ||
1494 | { | ||
1495 | struct brcmnand_host *host = chip->priv; | ||
1496 | u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL; | ||
1497 | int ret; | ||
1498 | |||
1499 | brcmnand_set_ecc_enabled(host, 0); | ||
1500 | ret = brcmnand_read(mtd, chip, host->last_addr, | ||
1501 | mtd->writesize >> FC_SHIFT, (u32 *)buf, oob); | ||
1502 | brcmnand_set_ecc_enabled(host, 1); | ||
1503 | return ret; | ||
1504 | } | ||
1505 | |||
1506 | static int brcmnand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, | ||
1507 | int page) | ||
1508 | { | ||
1509 | return brcmnand_read(mtd, chip, (u64)page << chip->page_shift, | ||
1510 | mtd->writesize >> FC_SHIFT, | ||
1511 | NULL, (u8 *)chip->oob_poi); | ||
1512 | } | ||
1513 | |||
1514 | static int brcmnand_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, | ||
1515 | int page) | ||
1516 | { | ||
1517 | struct brcmnand_host *host = chip->priv; | ||
1518 | |||
1519 | brcmnand_set_ecc_enabled(host, 0); | ||
1520 | brcmnand_read(mtd, chip, (u64)page << chip->page_shift, | ||
1521 | mtd->writesize >> FC_SHIFT, | ||
1522 | NULL, (u8 *)chip->oob_poi); | ||
1523 | brcmnand_set_ecc_enabled(host, 1); | ||
1524 | return 0; | ||
1525 | } | ||
1526 | |||
1527 | static int brcmnand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | ||
1528 | uint32_t data_offs, uint32_t readlen, | ||
1529 | uint8_t *bufpoi, int page) | ||
1530 | { | ||
1531 | struct brcmnand_host *host = chip->priv; | ||
1532 | |||
1533 | return brcmnand_read(mtd, chip, host->last_addr + data_offs, | ||
1534 | readlen >> FC_SHIFT, (u32 *)bufpoi, NULL); | ||
1535 | } | ||
1536 | |||
1537 | static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip, | ||
1538 | u64 addr, const u32 *buf, u8 *oob) | ||
1539 | { | ||
1540 | struct brcmnand_host *host = chip->priv; | ||
1541 | struct brcmnand_controller *ctrl = host->ctrl; | ||
1542 | unsigned int i, j, trans = mtd->writesize >> FC_SHIFT; | ||
1543 | int status, ret = 0; | ||
1544 | |||
1545 | dev_dbg(ctrl->dev, "write %llx <- %p\n", (unsigned long long)addr, buf); | ||
1546 | |||
1547 | if (unlikely((u32)buf & 0x03)) { | ||
1548 | dev_warn(ctrl->dev, "unaligned buffer: %p\n", buf); | ||
1549 | buf = (u32 *)((u32)buf & ~0x03); | ||
1550 | } | ||
1551 | |||
1552 | brcmnand_wp(mtd, 0); | ||
1553 | |||
1554 | for (i = 0; i < ctrl->max_oob; i += 4) | ||
1555 | oob_reg_write(ctrl, i, 0xffffffff); | ||
1556 | |||
1557 | if (has_flash_dma(ctrl) && !oob && flash_dma_buf_ok(buf)) { | ||
1558 | if (brcmnand_dma_trans(host, addr, (u32 *)buf, | ||
1559 | mtd->writesize, CMD_PROGRAM_PAGE)) | ||
1560 | ret = -EIO; | ||
1561 | goto out; | ||
1562 | } | ||
1563 | |||
1564 | brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS, | ||
1565 | (host->cs << 16) | ((addr >> 32) & 0xffff)); | ||
1566 | (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS); | ||
1567 | |||
1568 | for (i = 0; i < trans; i++, addr += FC_BYTES) { | ||
1569 | /* full address MUST be set before populating FC */ | ||
1570 | brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS, | ||
1571 | lower_32_bits(addr)); | ||
1572 | (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS); | ||
1573 | |||
1574 | if (buf) { | ||
1575 | brcmnand_soc_data_bus_prepare(ctrl->soc); | ||
1576 | |||
1577 | for (j = 0; j < FC_WORDS; j++, buf++) | ||
1578 | brcmnand_write_fc(ctrl, j, *buf); | ||
1579 | |||
1580 | brcmnand_soc_data_bus_unprepare(ctrl->soc); | ||
1581 | } else if (oob) { | ||
1582 | for (j = 0; j < FC_WORDS; j++) | ||
1583 | brcmnand_write_fc(ctrl, j, 0xffffffff); | ||
1584 | } | ||
1585 | |||
1586 | if (oob) { | ||
1587 | oob += write_oob_to_regs(ctrl, i, oob, | ||
1588 | mtd->oobsize / trans, | ||
1589 | host->hwcfg.sector_size_1k); | ||
1590 | } | ||
1591 | |||
1592 | /* we cannot use SPARE_AREA_PROGRAM when PARTIAL_PAGE_EN=0 */ | ||
1593 | brcmnand_send_cmd(host, CMD_PROGRAM_PAGE); | ||
1594 | status = brcmnand_waitfunc(mtd, chip); | ||
1595 | |||
1596 | if (status & NAND_STATUS_FAIL) { | ||
1597 | dev_info(ctrl->dev, "program failed at %llx\n", | ||
1598 | (unsigned long long)addr); | ||
1599 | ret = -EIO; | ||
1600 | goto out; | ||
1601 | } | ||
1602 | } | ||
1603 | out: | ||
1604 | brcmnand_wp(mtd, 1); | ||
1605 | return ret; | ||
1606 | } | ||
1607 | |||
1608 | static int brcmnand_write_page(struct mtd_info *mtd, struct nand_chip *chip, | ||
1609 | const uint8_t *buf, int oob_required) | ||
1610 | { | ||
1611 | struct brcmnand_host *host = chip->priv; | ||
1612 | void *oob = oob_required ? chip->oob_poi : NULL; | ||
1613 | |||
1614 | brcmnand_write(mtd, chip, host->last_addr, (const u32 *)buf, oob); | ||
1615 | return 0; | ||
1616 | } | ||
1617 | |||
1618 | static int brcmnand_write_page_raw(struct mtd_info *mtd, | ||
1619 | struct nand_chip *chip, const uint8_t *buf, | ||
1620 | int oob_required) | ||
1621 | { | ||
1622 | struct brcmnand_host *host = chip->priv; | ||
1623 | void *oob = oob_required ? chip->oob_poi : NULL; | ||
1624 | |||
1625 | brcmnand_set_ecc_enabled(host, 0); | ||
1626 | brcmnand_write(mtd, chip, host->last_addr, (const u32 *)buf, oob); | ||
1627 | brcmnand_set_ecc_enabled(host, 1); | ||
1628 | return 0; | ||
1629 | } | ||
1630 | |||
1631 | static int brcmnand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, | ||
1632 | int page) | ||
1633 | { | ||
1634 | return brcmnand_write(mtd, chip, (u64)page << chip->page_shift, | ||
1635 | NULL, chip->oob_poi); | ||
1636 | } | ||
1637 | |||
1638 | static int brcmnand_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, | ||
1639 | int page) | ||
1640 | { | ||
1641 | struct brcmnand_host *host = chip->priv; | ||
1642 | int ret; | ||
1643 | |||
1644 | brcmnand_set_ecc_enabled(host, 0); | ||
1645 | ret = brcmnand_write(mtd, chip, (u64)page << chip->page_shift, NULL, | ||
1646 | (u8 *)chip->oob_poi); | ||
1647 | brcmnand_set_ecc_enabled(host, 1); | ||
1648 | |||
1649 | return ret; | ||
1650 | } | ||
1651 | |||
1652 | /*********************************************************************** | ||
1653 | * Per-CS setup (1 NAND device) | ||
1654 | ***********************************************************************/ | ||
1655 | |||
1656 | static int brcmnand_set_cfg(struct brcmnand_host *host, | ||
1657 | struct brcmnand_cfg *cfg) | ||
1658 | { | ||
1659 | struct brcmnand_controller *ctrl = host->ctrl; | ||
1660 | struct nand_chip *chip = &host->chip; | ||
1661 | u16 cfg_offs = brcmnand_cs_offset(ctrl, host->cs, BRCMNAND_CS_CFG); | ||
1662 | u16 cfg_ext_offs = brcmnand_cs_offset(ctrl, host->cs, | ||
1663 | BRCMNAND_CS_CFG_EXT); | ||
1664 | u16 acc_control_offs = brcmnand_cs_offset(ctrl, host->cs, | ||
1665 | BRCMNAND_CS_ACC_CONTROL); | ||
1666 | u8 block_size = 0, page_size = 0, device_size = 0; | ||
1667 | u32 tmp; | ||
1668 | |||
1669 | if (ctrl->block_sizes) { | ||
1670 | int i, found; | ||
1671 | |||
1672 | for (i = 0, found = 0; ctrl->block_sizes[i]; i++) | ||
1673 | if (ctrl->block_sizes[i] * 1024 == cfg->block_size) { | ||
1674 | block_size = i; | ||
1675 | found = 1; | ||
1676 | } | ||
1677 | if (!found) { | ||
1678 | dev_warn(ctrl->dev, "invalid block size %u\n", | ||
1679 | cfg->block_size); | ||
1680 | return -EINVAL; | ||
1681 | } | ||
1682 | } else { | ||
1683 | block_size = ffs(cfg->block_size) - ffs(BRCMNAND_MIN_BLOCKSIZE); | ||
1684 | } | ||
1685 | |||
1686 | if (cfg->block_size < BRCMNAND_MIN_BLOCKSIZE || (ctrl->max_block_size && | ||
1687 | cfg->block_size > ctrl->max_block_size)) { | ||
1688 | dev_warn(ctrl->dev, "invalid block size %u\n", | ||
1689 | cfg->block_size); | ||
1690 | block_size = 0; | ||
1691 | } | ||
1692 | |||
1693 | if (ctrl->page_sizes) { | ||
1694 | int i, found; | ||
1695 | |||
1696 | for (i = 0, found = 0; ctrl->page_sizes[i]; i++) | ||
1697 | if (ctrl->page_sizes[i] == cfg->page_size) { | ||
1698 | page_size = i; | ||
1699 | found = 1; | ||
1700 | } | ||
1701 | if (!found) { | ||
1702 | dev_warn(ctrl->dev, "invalid page size %u\n", | ||
1703 | cfg->page_size); | ||
1704 | return -EINVAL; | ||
1705 | } | ||
1706 | } else { | ||
1707 | page_size = ffs(cfg->page_size) - ffs(BRCMNAND_MIN_PAGESIZE); | ||
1708 | } | ||
1709 | |||
1710 | if (cfg->page_size < BRCMNAND_MIN_PAGESIZE || (ctrl->max_page_size && | ||
1711 | cfg->page_size > ctrl->max_page_size)) { | ||
1712 | dev_warn(ctrl->dev, "invalid page size %u\n", cfg->page_size); | ||
1713 | return -EINVAL; | ||
1714 | } | ||
1715 | |||
1716 | if (fls64(cfg->device_size) < fls64(BRCMNAND_MIN_DEVSIZE)) { | ||
1717 | dev_warn(ctrl->dev, "invalid device size 0x%llx\n", | ||
1718 | (unsigned long long)cfg->device_size); | ||
1719 | return -EINVAL; | ||
1720 | } | ||
1721 | device_size = fls64(cfg->device_size) - fls64(BRCMNAND_MIN_DEVSIZE); | ||
1722 | |||
1723 | tmp = (cfg->blk_adr_bytes << 8) | | ||
1724 | (cfg->col_adr_bytes << 12) | | ||
1725 | (cfg->ful_adr_bytes << 16) | | ||
1726 | (!!(cfg->device_width == 16) << 23) | | ||
1727 | (device_size << 24); | ||
1728 | if (cfg_offs == cfg_ext_offs) { | ||
1729 | tmp |= (page_size << 20) | (block_size << 28); | ||
1730 | nand_writereg(ctrl, cfg_offs, tmp); | ||
1731 | } else { | ||
1732 | nand_writereg(ctrl, cfg_offs, tmp); | ||
1733 | tmp = page_size | (block_size << 4); | ||
1734 | nand_writereg(ctrl, cfg_ext_offs, tmp); | ||
1735 | } | ||
1736 | |||
1737 | tmp = nand_readreg(ctrl, acc_control_offs); | ||
1738 | tmp &= ~brcmnand_ecc_level_mask(ctrl); | ||
1739 | tmp |= cfg->ecc_level << NAND_ACC_CONTROL_ECC_SHIFT; | ||
1740 | tmp &= ~brcmnand_spare_area_mask(ctrl); | ||
1741 | tmp |= cfg->spare_area_size; | ||
1742 | nand_writereg(ctrl, acc_control_offs, tmp); | ||
1743 | |||
1744 | brcmnand_set_sector_size_1k(host, cfg->sector_size_1k); | ||
1745 | |||
1746 | /* threshold = ceil(BCH-level * 0.75) */ | ||
1747 | brcmnand_wr_corr_thresh(host, DIV_ROUND_UP(chip->ecc.strength * 3, 4)); | ||
1748 | |||
1749 | return 0; | ||
1750 | } | ||
1751 | |||
1752 | static void brcmnand_print_cfg(char *buf, struct brcmnand_cfg *cfg) | ||
1753 | { | ||
1754 | buf += sprintf(buf, | ||
1755 | "%lluMiB total, %uKiB blocks, %u%s pages, %uB OOB, %u-bit", | ||
1756 | (unsigned long long)cfg->device_size >> 20, | ||
1757 | cfg->block_size >> 10, | ||
1758 | cfg->page_size >= 1024 ? cfg->page_size >> 10 : cfg->page_size, | ||
1759 | cfg->page_size >= 1024 ? "KiB" : "B", | ||
1760 | cfg->spare_area_size, cfg->device_width); | ||
1761 | |||
1762 | /* Account for Hamming ECC and for BCH 512B vs 1KiB sectors */ | ||
1763 | if (is_hamming_ecc(cfg)) | ||
1764 | sprintf(buf, ", Hamming ECC"); | ||
1765 | else if (cfg->sector_size_1k) | ||
1766 | sprintf(buf, ", BCH-%u (1KiB sector)", cfg->ecc_level << 1); | ||
1767 | else | ||
1768 | sprintf(buf, ", BCH-%u", cfg->ecc_level); | ||
1769 | } | ||
1770 | |||
1771 | /* | ||
1772 | * Minimum number of bytes to address a page. Calculated as: | ||
1773 | * roundup(log2(size / page-size) / 8) | ||
1774 | * | ||
1775 | * NB: the following does not "round up" for non-power-of-2 'size'; but this is | ||
1776 | * OK because many other things will break if 'size' is irregular... | ||
1777 | */ | ||
1778 | static inline int get_blk_adr_bytes(u64 size, u32 writesize) | ||
1779 | { | ||
1780 | return ALIGN(ilog2(size) - ilog2(writesize), 8) >> 3; | ||
1781 | } | ||
1782 | |||
1783 | static int brcmnand_setup_dev(struct brcmnand_host *host) | ||
1784 | { | ||
1785 | struct mtd_info *mtd = &host->mtd; | ||
1786 | struct nand_chip *chip = &host->chip; | ||
1787 | struct brcmnand_controller *ctrl = host->ctrl; | ||
1788 | struct brcmnand_cfg *cfg = &host->hwcfg; | ||
1789 | char msg[128]; | ||
1790 | u32 offs, tmp, oob_sector; | ||
1791 | int ret; | ||
1792 | |||
1793 | memset(cfg, 0, sizeof(*cfg)); | ||
1794 | |||
1795 | ret = of_property_read_u32(chip->dn, "brcm,nand-oob-sector-size", | ||
1796 | &oob_sector); | ||
1797 | if (ret) { | ||
1798 | /* Use detected size */ | ||
1799 | cfg->spare_area_size = mtd->oobsize / | ||
1800 | (mtd->writesize >> FC_SHIFT); | ||
1801 | } else { | ||
1802 | cfg->spare_area_size = oob_sector; | ||
1803 | } | ||
1804 | if (cfg->spare_area_size > ctrl->max_oob) | ||
1805 | cfg->spare_area_size = ctrl->max_oob; | ||
1806 | /* | ||
1807 | * Set oobsize to be consistent with controller's spare_area_size, as | ||
1808 | * the rest is inaccessible. | ||
1809 | */ | ||
1810 | mtd->oobsize = cfg->spare_area_size * (mtd->writesize >> FC_SHIFT); | ||
1811 | |||
1812 | cfg->device_size = mtd->size; | ||
1813 | cfg->block_size = mtd->erasesize; | ||
1814 | cfg->page_size = mtd->writesize; | ||
1815 | cfg->device_width = (chip->options & NAND_BUSWIDTH_16) ? 16 : 8; | ||
1816 | cfg->col_adr_bytes = 2; | ||
1817 | cfg->blk_adr_bytes = get_blk_adr_bytes(mtd->size, mtd->writesize); | ||
1818 | |||
1819 | switch (chip->ecc.size) { | ||
1820 | case 512: | ||
1821 | if (chip->ecc.strength == 1) /* Hamming */ | ||
1822 | cfg->ecc_level = 15; | ||
1823 | else | ||
1824 | cfg->ecc_level = chip->ecc.strength; | ||
1825 | cfg->sector_size_1k = 0; | ||
1826 | break; | ||
1827 | case 1024: | ||
1828 | if (!(ctrl->features & BRCMNAND_HAS_1K_SECTORS)) { | ||
1829 | dev_err(ctrl->dev, "1KB sectors not supported\n"); | ||
1830 | return -EINVAL; | ||
1831 | } | ||
1832 | if (chip->ecc.strength & 0x1) { | ||
1833 | dev_err(ctrl->dev, | ||
1834 | "odd ECC not supported with 1KB sectors\n"); | ||
1835 | return -EINVAL; | ||
1836 | } | ||
1837 | |||
1838 | cfg->ecc_level = chip->ecc.strength >> 1; | ||
1839 | cfg->sector_size_1k = 1; | ||
1840 | break; | ||
1841 | default: | ||
1842 | dev_err(ctrl->dev, "unsupported ECC size: %d\n", | ||
1843 | chip->ecc.size); | ||
1844 | return -EINVAL; | ||
1845 | } | ||
1846 | |||
1847 | cfg->ful_adr_bytes = cfg->blk_adr_bytes; | ||
1848 | if (mtd->writesize > 512) | ||
1849 | cfg->ful_adr_bytes += cfg->col_adr_bytes; | ||
1850 | else | ||
1851 | cfg->ful_adr_bytes += 1; | ||
1852 | |||
1853 | ret = brcmnand_set_cfg(host, cfg); | ||
1854 | if (ret) | ||
1855 | return ret; | ||
1856 | |||
1857 | brcmnand_set_ecc_enabled(host, 1); | ||
1858 | |||
1859 | brcmnand_print_cfg(msg, cfg); | ||
1860 | dev_info(ctrl->dev, "detected %s\n", msg); | ||
1861 | |||
1862 | /* Configure ACC_CONTROL */ | ||
1863 | offs = brcmnand_cs_offset(ctrl, host->cs, BRCMNAND_CS_ACC_CONTROL); | ||
1864 | tmp = nand_readreg(ctrl, offs); | ||
1865 | tmp &= ~ACC_CONTROL_PARTIAL_PAGE; | ||
1866 | tmp &= ~ACC_CONTROL_RD_ERASED; | ||
1867 | tmp &= ~ACC_CONTROL_FAST_PGM_RDIN; | ||
1868 | if (ctrl->features & BRCMNAND_HAS_PREFETCH) { | ||
1869 | /* | ||
1870 | * FIXME: Flash DMA + prefetch may see spurious erased-page ECC | ||
1871 | * errors | ||
1872 | */ | ||
1873 | if (has_flash_dma(ctrl)) | ||
1874 | tmp &= ~ACC_CONTROL_PREFETCH; | ||
1875 | else | ||
1876 | tmp |= ACC_CONTROL_PREFETCH; | ||
1877 | } | ||
1878 | nand_writereg(ctrl, offs, tmp); | ||
1879 | |||
1880 | return 0; | ||
1881 | } | ||
1882 | |||
1883 | static int brcmnand_init_cs(struct brcmnand_host *host) | ||
1884 | { | ||
1885 | struct brcmnand_controller *ctrl = host->ctrl; | ||
1886 | struct device_node *dn = host->of_node; | ||
1887 | struct platform_device *pdev = host->pdev; | ||
1888 | struct mtd_info *mtd; | ||
1889 | struct nand_chip *chip; | ||
1890 | int ret; | ||
1891 | struct mtd_part_parser_data ppdata = { .of_node = dn }; | ||
1892 | |||
1893 | ret = of_property_read_u32(dn, "reg", &host->cs); | ||
1894 | if (ret) { | ||
1895 | dev_err(&pdev->dev, "can't get chip-select\n"); | ||
1896 | return -ENXIO; | ||
1897 | } | ||
1898 | |||
1899 | mtd = &host->mtd; | ||
1900 | chip = &host->chip; | ||
1901 | |||
1902 | chip->dn = dn; | ||
1903 | chip->priv = host; | ||
1904 | mtd->priv = chip; | ||
1905 | mtd->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "brcmnand.%d", | ||
1906 | host->cs); | ||
1907 | mtd->owner = THIS_MODULE; | ||
1908 | mtd->dev.parent = &pdev->dev; | ||
1909 | |||
1910 | chip->IO_ADDR_R = (void __iomem *)0xdeadbeef; | ||
1911 | chip->IO_ADDR_W = (void __iomem *)0xdeadbeef; | ||
1912 | |||
1913 | chip->cmd_ctrl = brcmnand_cmd_ctrl; | ||
1914 | chip->cmdfunc = brcmnand_cmdfunc; | ||
1915 | chip->waitfunc = brcmnand_waitfunc; | ||
1916 | chip->read_byte = brcmnand_read_byte; | ||
1917 | chip->read_buf = brcmnand_read_buf; | ||
1918 | chip->write_buf = brcmnand_write_buf; | ||
1919 | |||
1920 | chip->ecc.mode = NAND_ECC_HW; | ||
1921 | chip->ecc.read_page = brcmnand_read_page; | ||
1922 | chip->ecc.read_subpage = brcmnand_read_subpage; | ||
1923 | chip->ecc.write_page = brcmnand_write_page; | ||
1924 | chip->ecc.read_page_raw = brcmnand_read_page_raw; | ||
1925 | chip->ecc.write_page_raw = brcmnand_write_page_raw; | ||
1926 | chip->ecc.write_oob_raw = brcmnand_write_oob_raw; | ||
1927 | chip->ecc.read_oob_raw = brcmnand_read_oob_raw; | ||
1928 | chip->ecc.read_oob = brcmnand_read_oob; | ||
1929 | chip->ecc.write_oob = brcmnand_write_oob; | ||
1930 | |||
1931 | chip->controller = &ctrl->controller; | ||
1932 | |||
1933 | if (nand_scan_ident(mtd, 1, NULL)) | ||
1934 | return -ENXIO; | ||
1935 | |||
1936 | chip->options |= NAND_NO_SUBPAGE_WRITE; | ||
1937 | /* | ||
1938 | * Avoid (for instance) kmap()'d buffers from JFFS2, which we can't DMA | ||
1939 | * to/from, and have nand_base pass us a bounce buffer instead, as | ||
1940 | * needed. | ||
1941 | */ | ||
1942 | chip->options |= NAND_USE_BOUNCE_BUFFER; | ||
1943 | |||
1944 | if (of_get_nand_on_flash_bbt(dn)) | ||
1945 | chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; | ||
1946 | |||
1947 | if (brcmnand_setup_dev(host)) | ||
1948 | return -ENXIO; | ||
1949 | |||
1950 | chip->ecc.size = host->hwcfg.sector_size_1k ? 1024 : 512; | ||
1951 | /* only use our internal HW threshold */ | ||
1952 | mtd->bitflip_threshold = 1; | ||
1953 | |||
1954 | chip->ecc.layout = brcmstb_choose_ecc_layout(host); | ||
1955 | if (!chip->ecc.layout) | ||
1956 | return -ENXIO; | ||
1957 | |||
1958 | if (nand_scan_tail(mtd)) | ||
1959 | return -ENXIO; | ||
1960 | |||
1961 | return mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); | ||
1962 | } | ||
1963 | |||
1964 | static void brcmnand_save_restore_cs_config(struct brcmnand_host *host, | ||
1965 | int restore) | ||
1966 | { | ||
1967 | struct brcmnand_controller *ctrl = host->ctrl; | ||
1968 | u16 cfg_offs = brcmnand_cs_offset(ctrl, host->cs, BRCMNAND_CS_CFG); | ||
1969 | u16 cfg_ext_offs = brcmnand_cs_offset(ctrl, host->cs, | ||
1970 | BRCMNAND_CS_CFG_EXT); | ||
1971 | u16 acc_control_offs = brcmnand_cs_offset(ctrl, host->cs, | ||
1972 | BRCMNAND_CS_ACC_CONTROL); | ||
1973 | u16 t1_offs = brcmnand_cs_offset(ctrl, host->cs, BRCMNAND_CS_TIMING1); | ||
1974 | u16 t2_offs = brcmnand_cs_offset(ctrl, host->cs, BRCMNAND_CS_TIMING2); | ||
1975 | |||
1976 | if (restore) { | ||
1977 | nand_writereg(ctrl, cfg_offs, host->hwcfg.config); | ||
1978 | if (cfg_offs != cfg_ext_offs) | ||
1979 | nand_writereg(ctrl, cfg_ext_offs, | ||
1980 | host->hwcfg.config_ext); | ||
1981 | nand_writereg(ctrl, acc_control_offs, host->hwcfg.acc_control); | ||
1982 | nand_writereg(ctrl, t1_offs, host->hwcfg.timing_1); | ||
1983 | nand_writereg(ctrl, t2_offs, host->hwcfg.timing_2); | ||
1984 | } else { | ||
1985 | host->hwcfg.config = nand_readreg(ctrl, cfg_offs); | ||
1986 | if (cfg_offs != cfg_ext_offs) | ||
1987 | host->hwcfg.config_ext = | ||
1988 | nand_readreg(ctrl, cfg_ext_offs); | ||
1989 | host->hwcfg.acc_control = nand_readreg(ctrl, acc_control_offs); | ||
1990 | host->hwcfg.timing_1 = nand_readreg(ctrl, t1_offs); | ||
1991 | host->hwcfg.timing_2 = nand_readreg(ctrl, t2_offs); | ||
1992 | } | ||
1993 | } | ||
1994 | |||
1995 | static int brcmnand_suspend(struct device *dev) | ||
1996 | { | ||
1997 | struct brcmnand_controller *ctrl = dev_get_drvdata(dev); | ||
1998 | struct brcmnand_host *host; | ||
1999 | |||
2000 | list_for_each_entry(host, &ctrl->host_list, node) | ||
2001 | brcmnand_save_restore_cs_config(host, 0); | ||
2002 | |||
2003 | ctrl->nand_cs_nand_select = brcmnand_read_reg(ctrl, BRCMNAND_CS_SELECT); | ||
2004 | ctrl->nand_cs_nand_xor = brcmnand_read_reg(ctrl, BRCMNAND_CS_XOR); | ||
2005 | ctrl->corr_stat_threshold = | ||
2006 | brcmnand_read_reg(ctrl, BRCMNAND_CORR_THRESHOLD); | ||
2007 | |||
2008 | if (has_flash_dma(ctrl)) | ||
2009 | ctrl->flash_dma_mode = flash_dma_readl(ctrl, FLASH_DMA_MODE); | ||
2010 | |||
2011 | return 0; | ||
2012 | } | ||
2013 | |||
2014 | static int brcmnand_resume(struct device *dev) | ||
2015 | { | ||
2016 | struct brcmnand_controller *ctrl = dev_get_drvdata(dev); | ||
2017 | struct brcmnand_host *host; | ||
2018 | |||
2019 | if (has_flash_dma(ctrl)) { | ||
2020 | flash_dma_writel(ctrl, FLASH_DMA_MODE, ctrl->flash_dma_mode); | ||
2021 | flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0); | ||
2022 | } | ||
2023 | |||
2024 | brcmnand_write_reg(ctrl, BRCMNAND_CS_SELECT, ctrl->nand_cs_nand_select); | ||
2025 | brcmnand_write_reg(ctrl, BRCMNAND_CS_XOR, ctrl->nand_cs_nand_xor); | ||
2026 | brcmnand_write_reg(ctrl, BRCMNAND_CORR_THRESHOLD, | ||
2027 | ctrl->corr_stat_threshold); | ||
2028 | if (ctrl->soc) { | ||
2029 | /* Clear/re-enable interrupt */ | ||
2030 | ctrl->soc->ctlrdy_ack(ctrl->soc); | ||
2031 | ctrl->soc->ctlrdy_set_enabled(ctrl->soc, true); | ||
2032 | } | ||
2033 | |||
2034 | list_for_each_entry(host, &ctrl->host_list, node) { | ||
2035 | struct mtd_info *mtd = &host->mtd; | ||
2036 | struct nand_chip *chip = mtd->priv; | ||
2037 | |||
2038 | brcmnand_save_restore_cs_config(host, 1); | ||
2039 | |||
2040 | /* Reset the chip, required by some chips after power-up */ | ||
2041 | chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); | ||
2042 | } | ||
2043 | |||
2044 | return 0; | ||
2045 | } | ||
2046 | |||
2047 | const struct dev_pm_ops brcmnand_pm_ops = { | ||
2048 | .suspend = brcmnand_suspend, | ||
2049 | .resume = brcmnand_resume, | ||
2050 | }; | ||
2051 | EXPORT_SYMBOL_GPL(brcmnand_pm_ops); | ||
2052 | |||
2053 | static const struct of_device_id brcmnand_of_match[] = { | ||
2054 | { .compatible = "brcm,brcmnand-v4.0" }, | ||
2055 | { .compatible = "brcm,brcmnand-v5.0" }, | ||
2056 | { .compatible = "brcm,brcmnand-v6.0" }, | ||
2057 | { .compatible = "brcm,brcmnand-v6.1" }, | ||
2058 | { .compatible = "brcm,brcmnand-v7.0" }, | ||
2059 | { .compatible = "brcm,brcmnand-v7.1" }, | ||
2060 | {}, | ||
2061 | }; | ||
2062 | MODULE_DEVICE_TABLE(of, brcmnand_of_match); | ||
2063 | |||
2064 | /*********************************************************************** | ||
2065 | * Platform driver setup (per controller) | ||
2066 | ***********************************************************************/ | ||
2067 | |||
2068 | int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) | ||
2069 | { | ||
2070 | struct device *dev = &pdev->dev; | ||
2071 | struct device_node *dn = dev->of_node, *child; | ||
2072 | struct brcmnand_controller *ctrl; | ||
2073 | struct resource *res; | ||
2074 | int ret; | ||
2075 | |||
2076 | /* We only support device-tree instantiation */ | ||
2077 | if (!dn) | ||
2078 | return -ENODEV; | ||
2079 | |||
2080 | if (!of_match_node(brcmnand_of_match, dn)) | ||
2081 | return -ENODEV; | ||
2082 | |||
2083 | ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); | ||
2084 | if (!ctrl) | ||
2085 | return -ENOMEM; | ||
2086 | |||
2087 | dev_set_drvdata(dev, ctrl); | ||
2088 | ctrl->dev = dev; | ||
2089 | |||
2090 | init_completion(&ctrl->done); | ||
2091 | init_completion(&ctrl->dma_done); | ||
2092 | spin_lock_init(&ctrl->controller.lock); | ||
2093 | init_waitqueue_head(&ctrl->controller.wq); | ||
2094 | INIT_LIST_HEAD(&ctrl->host_list); | ||
2095 | |||
2096 | /* NAND register range */ | ||
2097 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
2098 | ctrl->nand_base = devm_ioremap_resource(dev, res); | ||
2099 | if (IS_ERR(ctrl->nand_base)) | ||
2100 | return PTR_ERR(ctrl->nand_base); | ||
2101 | |||
2102 | /* Initialize NAND revision */ | ||
2103 | ret = brcmnand_revision_init(ctrl); | ||
2104 | if (ret) | ||
2105 | return ret; | ||
2106 | |||
2107 | /* | ||
2108 | * Most chips have this cache at a fixed offset within 'nand' block. | ||
2109 | * Some must specify this region separately. | ||
2110 | */ | ||
2111 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand-cache"); | ||
2112 | if (res) { | ||
2113 | ctrl->nand_fc = devm_ioremap_resource(dev, res); | ||
2114 | if (IS_ERR(ctrl->nand_fc)) | ||
2115 | return PTR_ERR(ctrl->nand_fc); | ||
2116 | } else { | ||
2117 | ctrl->nand_fc = ctrl->nand_base + | ||
2118 | ctrl->reg_offsets[BRCMNAND_FC_BASE]; | ||
2119 | } | ||
2120 | |||
2121 | /* FLASH_DMA */ | ||
2122 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "flash-dma"); | ||
2123 | if (res) { | ||
2124 | ctrl->flash_dma_base = devm_ioremap_resource(dev, res); | ||
2125 | if (IS_ERR(ctrl->flash_dma_base)) | ||
2126 | return PTR_ERR(ctrl->flash_dma_base); | ||
2127 | |||
2128 | flash_dma_writel(ctrl, FLASH_DMA_MODE, 1); /* linked-list */ | ||
2129 | flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0); | ||
2130 | |||
2131 | /* Allocate descriptor(s) */ | ||
2132 | ctrl->dma_desc = dmam_alloc_coherent(dev, | ||
2133 | sizeof(*ctrl->dma_desc), | ||
2134 | &ctrl->dma_pa, GFP_KERNEL); | ||
2135 | if (!ctrl->dma_desc) | ||
2136 | return -ENOMEM; | ||
2137 | |||
2138 | ctrl->dma_irq = platform_get_irq(pdev, 1); | ||
2139 | if ((int)ctrl->dma_irq < 0) { | ||
2140 | dev_err(dev, "missing FLASH_DMA IRQ\n"); | ||
2141 | return -ENODEV; | ||
2142 | } | ||
2143 | |||
2144 | ret = devm_request_irq(dev, ctrl->dma_irq, | ||
2145 | brcmnand_dma_irq, 0, DRV_NAME, | ||
2146 | ctrl); | ||
2147 | if (ret < 0) { | ||
2148 | dev_err(dev, "can't allocate IRQ %d: error %d\n", | ||
2149 | ctrl->dma_irq, ret); | ||
2150 | return ret; | ||
2151 | } | ||
2152 | |||
2153 | dev_info(dev, "enabling FLASH_DMA\n"); | ||
2154 | } | ||
2155 | |||
2156 | /* Disable automatic device ID config, direct addressing */ | ||
2157 | brcmnand_rmw_reg(ctrl, BRCMNAND_CS_SELECT, | ||
2158 | CS_SELECT_AUTO_DEVICE_ID_CFG | 0xff, 0, 0); | ||
2159 | /* Disable XOR addressing */ | ||
2160 | brcmnand_rmw_reg(ctrl, BRCMNAND_CS_XOR, 0xff, 0, 0); | ||
2161 | |||
2162 | if (ctrl->features & BRCMNAND_HAS_WP) { | ||
2163 | /* Permanently disable write protection */ | ||
2164 | if (wp_on == 2) | ||
2165 | brcmnand_set_wp(ctrl, false); | ||
2166 | } else { | ||
2167 | wp_on = 0; | ||
2168 | } | ||
2169 | |||
2170 | /* IRQ */ | ||
2171 | ctrl->irq = platform_get_irq(pdev, 0); | ||
2172 | if ((int)ctrl->irq < 0) { | ||
2173 | dev_err(dev, "no IRQ defined\n"); | ||
2174 | return -ENODEV; | ||
2175 | } | ||
2176 | |||
2177 | /* | ||
2178 | * Some SoCs integrate this controller (e.g., its interrupt bits) in | ||
2179 | * interesting ways | ||
2180 | */ | ||
2181 | if (soc) { | ||
2182 | ctrl->soc = soc; | ||
2183 | |||
2184 | ret = devm_request_irq(dev, ctrl->irq, brcmnand_irq, 0, | ||
2185 | DRV_NAME, ctrl); | ||
2186 | |||
2187 | /* Enable interrupt */ | ||
2188 | ctrl->soc->ctlrdy_ack(ctrl->soc); | ||
2189 | ctrl->soc->ctlrdy_set_enabled(ctrl->soc, true); | ||
2190 | } else { | ||
2191 | /* Use standard interrupt infrastructure */ | ||
2192 | ret = devm_request_irq(dev, ctrl->irq, brcmnand_ctlrdy_irq, 0, | ||
2193 | DRV_NAME, ctrl); | ||
2194 | } | ||
2195 | if (ret < 0) { | ||
2196 | dev_err(dev, "can't allocate IRQ %d: error %d\n", | ||
2197 | ctrl->irq, ret); | ||
2198 | return ret; | ||
2199 | } | ||
2200 | |||
2201 | for_each_available_child_of_node(dn, child) { | ||
2202 | if (of_device_is_compatible(child, "brcm,nandcs")) { | ||
2203 | struct brcmnand_host *host; | ||
2204 | |||
2205 | host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); | ||
2206 | if (!host) | ||
2207 | return -ENOMEM; | ||
2208 | host->pdev = pdev; | ||
2209 | host->ctrl = ctrl; | ||
2210 | host->of_node = child; | ||
2211 | |||
2212 | ret = brcmnand_init_cs(host); | ||
2213 | if (ret) | ||
2214 | continue; /* Try all chip-selects */ | ||
2215 | |||
2216 | list_add_tail(&host->node, &ctrl->host_list); | ||
2217 | } | ||
2218 | } | ||
2219 | |||
2220 | /* No chip-selects could initialize properly */ | ||
2221 | if (list_empty(&ctrl->host_list)) | ||
2222 | return -ENODEV; | ||
2223 | |||
2224 | return 0; | ||
2225 | } | ||
2226 | EXPORT_SYMBOL_GPL(brcmnand_probe); | ||
2227 | |||
2228 | int brcmnand_remove(struct platform_device *pdev) | ||
2229 | { | ||
2230 | struct brcmnand_controller *ctrl = dev_get_drvdata(&pdev->dev); | ||
2231 | struct brcmnand_host *host; | ||
2232 | |||
2233 | list_for_each_entry(host, &ctrl->host_list, node) | ||
2234 | nand_release(&host->mtd); | ||
2235 | |||
2236 | dev_set_drvdata(&pdev->dev, NULL); | ||
2237 | |||
2238 | return 0; | ||
2239 | } | ||
2240 | EXPORT_SYMBOL_GPL(brcmnand_remove); | ||
2241 | |||
2242 | MODULE_LICENSE("GPL v2"); | ||
2243 | MODULE_AUTHOR("Kevin Cernekee"); | ||
2244 | MODULE_AUTHOR("Brian Norris"); | ||
2245 | MODULE_DESCRIPTION("NAND driver for Broadcom chips"); | ||
2246 | MODULE_ALIAS("platform:brcmnand"); | ||
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.h b/drivers/mtd/nand/brcmnand/brcmnand.h new file mode 100644 index 000000000000..a20c73630b7b --- /dev/null +++ b/drivers/mtd/nand/brcmnand/brcmnand.h | |||
@@ -0,0 +1,73 @@ | |||
1 | /* | ||
2 | * Copyright © 2015 Broadcom Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | #ifndef __BRCMNAND_H__ | ||
15 | #define __BRCMNAND_H__ | ||
16 | |||
17 | #include <linux/types.h> | ||
18 | #include <linux/io.h> | ||
19 | |||
20 | struct platform_device; | ||
21 | struct dev_pm_ops; | ||
22 | |||
23 | struct brcmnand_soc { | ||
24 | struct platform_device *pdev; | ||
25 | void *priv; | ||
26 | bool (*ctlrdy_ack)(struct brcmnand_soc *soc); | ||
27 | void (*ctlrdy_set_enabled)(struct brcmnand_soc *soc, bool en); | ||
28 | void (*prepare_data_bus)(struct brcmnand_soc *soc, bool prepare); | ||
29 | }; | ||
30 | |||
31 | static inline void brcmnand_soc_data_bus_prepare(struct brcmnand_soc *soc) | ||
32 | { | ||
33 | if (soc && soc->prepare_data_bus) | ||
34 | soc->prepare_data_bus(soc, true); | ||
35 | } | ||
36 | |||
37 | static inline void brcmnand_soc_data_bus_unprepare(struct brcmnand_soc *soc) | ||
38 | { | ||
39 | if (soc && soc->prepare_data_bus) | ||
40 | soc->prepare_data_bus(soc, false); | ||
41 | } | ||
42 | |||
43 | static inline u32 brcmnand_readl(void __iomem *addr) | ||
44 | { | ||
45 | /* | ||
46 | * MIPS endianness is configured by boot strap, which also reverses all | ||
47 | * bus endianness (i.e., big-endian CPU + big endian bus ==> native | ||
48 | * endian I/O). | ||
49 | * | ||
50 | * Other architectures (e.g., ARM) either do not support big endian, or | ||
51 | * else leave I/O in little endian mode. | ||
52 | */ | ||
53 | if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(__BIG_ENDIAN)) | ||
54 | return __raw_readl(addr); | ||
55 | else | ||
56 | return readl_relaxed(addr); | ||
57 | } | ||
58 | |||
59 | static inline void brcmnand_writel(u32 val, void __iomem *addr) | ||
60 | { | ||
61 | /* See brcmnand_readl() comments */ | ||
62 | if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(__BIG_ENDIAN)) | ||
63 | __raw_writel(val, addr); | ||
64 | else | ||
65 | writel_relaxed(val, addr); | ||
66 | } | ||
67 | |||
68 | int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc); | ||
69 | int brcmnand_remove(struct platform_device *pdev); | ||
70 | |||
71 | extern const struct dev_pm_ops brcmnand_pm_ops; | ||
72 | |||
73 | #endif /* __BRCMNAND_H__ */ | ||
diff --git a/drivers/mtd/nand/brcmnand/brcmstb_nand.c b/drivers/mtd/nand/brcmnand/brcmstb_nand.c new file mode 100644 index 000000000000..5c271077ac87 --- /dev/null +++ b/drivers/mtd/nand/brcmnand/brcmstb_nand.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Copyright © 2015 Broadcom Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | |||
18 | #include "brcmnand.h" | ||
19 | |||
20 | static const struct of_device_id brcmstb_nand_of_match[] = { | ||
21 | { .compatible = "brcm,brcmnand" }, | ||
22 | {}, | ||
23 | }; | ||
24 | MODULE_DEVICE_TABLE(of, brcmstb_nand_of_match); | ||
25 | |||
26 | static int brcmstb_nand_probe(struct platform_device *pdev) | ||
27 | { | ||
28 | return brcmnand_probe(pdev, NULL); | ||
29 | } | ||
30 | |||
31 | static struct platform_driver brcmstb_nand_driver = { | ||
32 | .probe = brcmstb_nand_probe, | ||
33 | .remove = brcmnand_remove, | ||
34 | .driver = { | ||
35 | .name = "brcmstb_nand", | ||
36 | .pm = &brcmnand_pm_ops, | ||
37 | .of_match_table = brcmstb_nand_of_match, | ||
38 | } | ||
39 | }; | ||
40 | module_platform_driver(brcmstb_nand_driver); | ||
41 | |||
42 | MODULE_LICENSE("GPL v2"); | ||
43 | MODULE_AUTHOR("Brian Norris"); | ||
44 | MODULE_DESCRIPTION("NAND driver for Broadcom STB chips"); | ||
diff --git a/drivers/mtd/nand/brcmnand/iproc_nand.c b/drivers/mtd/nand/brcmnand/iproc_nand.c new file mode 100644 index 000000000000..683495c74620 --- /dev/null +++ b/drivers/mtd/nand/brcmnand/iproc_nand.c | |||
@@ -0,0 +1,150 @@ | |||
1 | /* | ||
2 | * Copyright © 2015 Broadcom Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/ioport.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/of_address.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/slab.h> | ||
22 | |||
23 | #include "brcmnand.h" | ||
24 | |||
25 | struct iproc_nand_soc_priv { | ||
26 | void __iomem *idm_base; | ||
27 | void __iomem *ext_base; | ||
28 | spinlock_t idm_lock; | ||
29 | }; | ||
30 | |||
31 | #define IPROC_NAND_CTLR_READY_OFFSET 0x10 | ||
32 | #define IPROC_NAND_CTLR_READY BIT(0) | ||
33 | |||
34 | #define IPROC_NAND_IO_CTRL_OFFSET 0x00 | ||
35 | #define IPROC_NAND_APB_LE_MODE BIT(24) | ||
36 | #define IPROC_NAND_INT_CTRL_READ_ENABLE BIT(6) | ||
37 | |||
38 | static bool iproc_nand_intc_ack(struct brcmnand_soc *soc) | ||
39 | { | ||
40 | struct iproc_nand_soc_priv *priv = soc->priv; | ||
41 | void __iomem *mmio = priv->ext_base + IPROC_NAND_CTLR_READY_OFFSET; | ||
42 | u32 val = brcmnand_readl(mmio); | ||
43 | |||
44 | if (val & IPROC_NAND_CTLR_READY) { | ||
45 | brcmnand_writel(IPROC_NAND_CTLR_READY, mmio); | ||
46 | return true; | ||
47 | } | ||
48 | |||
49 | return false; | ||
50 | } | ||
51 | |||
52 | static void iproc_nand_intc_set(struct brcmnand_soc *soc, bool en) | ||
53 | { | ||
54 | struct iproc_nand_soc_priv *priv = soc->priv; | ||
55 | void __iomem *mmio = priv->idm_base + IPROC_NAND_IO_CTRL_OFFSET; | ||
56 | u32 val; | ||
57 | unsigned long flags; | ||
58 | |||
59 | spin_lock_irqsave(&priv->idm_lock, flags); | ||
60 | |||
61 | val = brcmnand_readl(mmio); | ||
62 | |||
63 | if (en) | ||
64 | val |= IPROC_NAND_INT_CTRL_READ_ENABLE; | ||
65 | else | ||
66 | val &= ~IPROC_NAND_INT_CTRL_READ_ENABLE; | ||
67 | |||
68 | brcmnand_writel(val, mmio); | ||
69 | |||
70 | spin_unlock_irqrestore(&priv->idm_lock, flags); | ||
71 | } | ||
72 | |||
73 | static void iproc_nand_apb_access(struct brcmnand_soc *soc, bool prepare) | ||
74 | { | ||
75 | struct iproc_nand_soc_priv *priv = soc->priv; | ||
76 | void __iomem *mmio = priv->idm_base + IPROC_NAND_IO_CTRL_OFFSET; | ||
77 | u32 val; | ||
78 | unsigned long flags; | ||
79 | |||
80 | spin_lock_irqsave(&priv->idm_lock, flags); | ||
81 | |||
82 | val = brcmnand_readl(mmio); | ||
83 | |||
84 | if (prepare) | ||
85 | val |= IPROC_NAND_APB_LE_MODE; | ||
86 | else | ||
87 | val &= ~IPROC_NAND_APB_LE_MODE; | ||
88 | |||
89 | brcmnand_writel(val, mmio); | ||
90 | |||
91 | spin_unlock_irqrestore(&priv->idm_lock, flags); | ||
92 | } | ||
93 | |||
94 | static int iproc_nand_probe(struct platform_device *pdev) | ||
95 | { | ||
96 | struct device *dev = &pdev->dev; | ||
97 | struct iproc_nand_soc_priv *priv; | ||
98 | struct brcmnand_soc *soc; | ||
99 | struct resource *res; | ||
100 | |||
101 | soc = devm_kzalloc(dev, sizeof(*soc), GFP_KERNEL); | ||
102 | if (!soc) | ||
103 | return -ENOMEM; | ||
104 | |||
105 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
106 | if (!priv) | ||
107 | return -ENOMEM; | ||
108 | |||
109 | spin_lock_init(&priv->idm_lock); | ||
110 | |||
111 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iproc-idm"); | ||
112 | priv->idm_base = devm_ioremap_resource(dev, res); | ||
113 | if (IS_ERR(priv->idm_base)) | ||
114 | return PTR_ERR(priv->idm_base); | ||
115 | |||
116 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iproc-ext"); | ||
117 | priv->ext_base = devm_ioremap_resource(dev, res); | ||
118 | if (IS_ERR(priv->ext_base)) | ||
119 | return PTR_ERR(priv->ext_base); | ||
120 | |||
121 | soc->pdev = pdev; | ||
122 | soc->priv = priv; | ||
123 | soc->ctlrdy_ack = iproc_nand_intc_ack; | ||
124 | soc->ctlrdy_set_enabled = iproc_nand_intc_set; | ||
125 | soc->prepare_data_bus = iproc_nand_apb_access; | ||
126 | |||
127 | return brcmnand_probe(pdev, soc); | ||
128 | } | ||
129 | |||
130 | static const struct of_device_id iproc_nand_of_match[] = { | ||
131 | { .compatible = "brcm,nand-iproc" }, | ||
132 | {}, | ||
133 | }; | ||
134 | MODULE_DEVICE_TABLE(of, iproc_nand_of_match); | ||
135 | |||
136 | static struct platform_driver iproc_nand_driver = { | ||
137 | .probe = iproc_nand_probe, | ||
138 | .remove = brcmnand_remove, | ||
139 | .driver = { | ||
140 | .name = "iproc_nand", | ||
141 | .pm = &brcmnand_pm_ops, | ||
142 | .of_match_table = iproc_nand_of_match, | ||
143 | } | ||
144 | }; | ||
145 | module_platform_driver(iproc_nand_driver); | ||
146 | |||
147 | MODULE_LICENSE("GPL v2"); | ||
148 | MODULE_AUTHOR("Brian Norris"); | ||
149 | MODULE_AUTHOR("Ray Jui"); | ||
150 | MODULE_DESCRIPTION("NAND driver for Broadcom IPROC-based SoCs"); | ||
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c index 88109d375ae7..aec6045058c7 100644 --- a/drivers/mtd/nand/cs553x_nand.c +++ b/drivers/mtd/nand/cs553x_nand.c | |||
@@ -237,17 +237,23 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) | |||
237 | /* Enable the following for a flash based bad block table */ | 237 | /* Enable the following for a flash based bad block table */ |
238 | this->bbt_options = NAND_BBT_USE_FLASH; | 238 | this->bbt_options = NAND_BBT_USE_FLASH; |
239 | 239 | ||
240 | new_mtd->name = kasprintf(GFP_KERNEL, "cs553x_nand_cs%d", cs); | ||
241 | if (!new_mtd->name) { | ||
242 | err = -ENOMEM; | ||
243 | goto out_ior; | ||
244 | } | ||
245 | |||
240 | /* Scan to find existence of the device */ | 246 | /* Scan to find existence of the device */ |
241 | if (nand_scan(new_mtd, 1)) { | 247 | if (nand_scan(new_mtd, 1)) { |
242 | err = -ENXIO; | 248 | err = -ENXIO; |
243 | goto out_ior; | 249 | goto out_free; |
244 | } | 250 | } |
245 | 251 | ||
246 | new_mtd->name = kasprintf(GFP_KERNEL, "cs553x_nand_cs%d", cs); | ||
247 | |||
248 | cs553x_mtd[cs] = new_mtd; | 252 | cs553x_mtd[cs] = new_mtd; |
249 | goto out; | 253 | goto out; |
250 | 254 | ||
255 | out_free: | ||
256 | kfree(new_mtd->name); | ||
251 | out_ior: | 257 | out_ior: |
252 | iounmap(this->IO_ADDR_R); | 258 | iounmap(this->IO_ADDR_R); |
253 | out_mtd: | 259 | out_mtd: |
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index f68a7bccecdc..7da266a53979 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c | |||
@@ -69,6 +69,9 @@ struct doc_priv { | |||
69 | int mh0_page; | 69 | int mh0_page; |
70 | int mh1_page; | 70 | int mh1_page; |
71 | struct mtd_info *nextdoc; | 71 | struct mtd_info *nextdoc; |
72 | |||
73 | /* Handle the last stage of initialization (BBT scan, partitioning) */ | ||
74 | int (*late_init)(struct mtd_info *mtd); | ||
72 | }; | 75 | }; |
73 | 76 | ||
74 | /* This is the syndrome computed by the HW ecc generator upon reading an empty | 77 | /* This is the syndrome computed by the HW ecc generator upon reading an empty |
@@ -1294,14 +1297,11 @@ static int __init nftl_scan_bbt(struct mtd_info *mtd) | |||
1294 | this->bbt_md = NULL; | 1297 | this->bbt_md = NULL; |
1295 | } | 1298 | } |
1296 | 1299 | ||
1297 | /* It's safe to set bd=NULL below because NAND_BBT_CREATE is not set. | 1300 | ret = this->scan_bbt(mtd); |
1298 | At least as nand_bbt.c is currently written. */ | 1301 | if (ret) |
1299 | if ((ret = nand_scan_bbt(mtd, NULL))) | ||
1300 | return ret; | 1302 | return ret; |
1301 | mtd_device_register(mtd, NULL, 0); | 1303 | |
1302 | if (!no_autopart) | 1304 | return mtd_device_register(mtd, parts, no_autopart ? 0 : numparts); |
1303 | mtd_device_register(mtd, parts, numparts); | ||
1304 | return 0; | ||
1305 | } | 1305 | } |
1306 | 1306 | ||
1307 | static int __init inftl_scan_bbt(struct mtd_info *mtd) | 1307 | static int __init inftl_scan_bbt(struct mtd_info *mtd) |
@@ -1344,10 +1344,10 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd) | |||
1344 | this->bbt_md->pattern = "TBB_SYSM"; | 1344 | this->bbt_md->pattern = "TBB_SYSM"; |
1345 | } | 1345 | } |
1346 | 1346 | ||
1347 | /* It's safe to set bd=NULL below because NAND_BBT_CREATE is not set. | 1347 | ret = this->scan_bbt(mtd); |
1348 | At least as nand_bbt.c is currently written. */ | 1348 | if (ret) |
1349 | if ((ret = nand_scan_bbt(mtd, NULL))) | ||
1350 | return ret; | 1349 | return ret; |
1350 | |||
1351 | memset((char *)parts, 0, sizeof(parts)); | 1351 | memset((char *)parts, 0, sizeof(parts)); |
1352 | numparts = inftl_partscan(mtd, parts); | 1352 | numparts = inftl_partscan(mtd, parts); |
1353 | /* At least for now, require the INFTL Media Header. We could probably | 1353 | /* At least for now, require the INFTL Media Header. We could probably |
@@ -1355,10 +1355,7 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd) | |||
1355 | autopartitioning, but I want to give it more thought. */ | 1355 | autopartitioning, but I want to give it more thought. */ |
1356 | if (!numparts) | 1356 | if (!numparts) |
1357 | return -EIO; | 1357 | return -EIO; |
1358 | mtd_device_register(mtd, NULL, 0); | 1358 | return mtd_device_register(mtd, parts, no_autopart ? 0 : numparts); |
1359 | if (!no_autopart) | ||
1360 | mtd_device_register(mtd, parts, numparts); | ||
1361 | return 0; | ||
1362 | } | 1359 | } |
1363 | 1360 | ||
1364 | static inline int __init doc2000_init(struct mtd_info *mtd) | 1361 | static inline int __init doc2000_init(struct mtd_info *mtd) |
@@ -1369,7 +1366,7 @@ static inline int __init doc2000_init(struct mtd_info *mtd) | |||
1369 | this->read_byte = doc2000_read_byte; | 1366 | this->read_byte = doc2000_read_byte; |
1370 | this->write_buf = doc2000_writebuf; | 1367 | this->write_buf = doc2000_writebuf; |
1371 | this->read_buf = doc2000_readbuf; | 1368 | this->read_buf = doc2000_readbuf; |
1372 | this->scan_bbt = nftl_scan_bbt; | 1369 | doc->late_init = nftl_scan_bbt; |
1373 | 1370 | ||
1374 | doc->CDSNControl = CDSN_CTRL_FLASH_IO | CDSN_CTRL_ECC_IO; | 1371 | doc->CDSNControl = CDSN_CTRL_FLASH_IO | CDSN_CTRL_ECC_IO; |
1375 | doc2000_count_chips(mtd); | 1372 | doc2000_count_chips(mtd); |
@@ -1396,13 +1393,13 @@ static inline int __init doc2001_init(struct mtd_info *mtd) | |||
1396 | can have multiple chips. */ | 1393 | can have multiple chips. */ |
1397 | doc2000_count_chips(mtd); | 1394 | doc2000_count_chips(mtd); |
1398 | mtd->name = "DiskOnChip 2000 (INFTL Model)"; | 1395 | mtd->name = "DiskOnChip 2000 (INFTL Model)"; |
1399 | this->scan_bbt = inftl_scan_bbt; | 1396 | doc->late_init = inftl_scan_bbt; |
1400 | return (4 * doc->chips_per_floor); | 1397 | return (4 * doc->chips_per_floor); |
1401 | } else { | 1398 | } else { |
1402 | /* Bog-standard Millennium */ | 1399 | /* Bog-standard Millennium */ |
1403 | doc->chips_per_floor = 1; | 1400 | doc->chips_per_floor = 1; |
1404 | mtd->name = "DiskOnChip Millennium"; | 1401 | mtd->name = "DiskOnChip Millennium"; |
1405 | this->scan_bbt = nftl_scan_bbt; | 1402 | doc->late_init = nftl_scan_bbt; |
1406 | return 1; | 1403 | return 1; |
1407 | } | 1404 | } |
1408 | } | 1405 | } |
@@ -1415,7 +1412,7 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd) | |||
1415 | this->read_byte = doc2001plus_read_byte; | 1412 | this->read_byte = doc2001plus_read_byte; |
1416 | this->write_buf = doc2001plus_writebuf; | 1413 | this->write_buf = doc2001plus_writebuf; |
1417 | this->read_buf = doc2001plus_readbuf; | 1414 | this->read_buf = doc2001plus_readbuf; |
1418 | this->scan_bbt = inftl_scan_bbt; | 1415 | doc->late_init = inftl_scan_bbt; |
1419 | this->cmd_ctrl = NULL; | 1416 | this->cmd_ctrl = NULL; |
1420 | this->select_chip = doc2001plus_select_chip; | 1417 | this->select_chip = doc2001plus_select_chip; |
1421 | this->cmdfunc = doc2001plus_command; | 1418 | this->cmdfunc = doc2001plus_command; |
@@ -1591,6 +1588,8 @@ static int __init doc_probe(unsigned long physadr) | |||
1591 | nand->ecc.bytes = 6; | 1588 | nand->ecc.bytes = 6; |
1592 | nand->ecc.strength = 2; | 1589 | nand->ecc.strength = 2; |
1593 | nand->bbt_options = NAND_BBT_USE_FLASH; | 1590 | nand->bbt_options = NAND_BBT_USE_FLASH; |
1591 | /* Skip the automatic BBT scan so we can run it manually */ | ||
1592 | nand->options |= NAND_SKIP_BBTSCAN; | ||
1594 | 1593 | ||
1595 | doc->physadr = physadr; | 1594 | doc->physadr = physadr; |
1596 | doc->virtadr = virtadr; | 1595 | doc->virtadr = virtadr; |
@@ -1608,7 +1607,7 @@ static int __init doc_probe(unsigned long physadr) | |||
1608 | else | 1607 | else |
1609 | numchips = doc2001_init(mtd); | 1608 | numchips = doc2001_init(mtd); |
1610 | 1609 | ||
1611 | if ((ret = nand_scan(mtd, numchips))) { | 1610 | if ((ret = nand_scan(mtd, numchips)) || (ret = doc->late_init(mtd))) { |
1612 | /* DBB note: i believe nand_release is necessary here, as | 1611 | /* DBB note: i believe nand_release is necessary here, as |
1613 | buffers may have been allocated in nand_base. Check with | 1612 | buffers may have been allocated in nand_base. Check with |
1614 | Thomas. FIX ME! */ | 1613 | Thomas. FIX ME! */ |
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index e58af4bfa8c8..793872f18065 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c | |||
@@ -562,6 +562,7 @@ static int dma_xfer(struct fsmc_nand_data *host, void *buffer, int len, | |||
562 | dma_cookie_t cookie; | 562 | dma_cookie_t cookie; |
563 | unsigned long flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; | 563 | unsigned long flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; |
564 | int ret; | 564 | int ret; |
565 | unsigned long time_left; | ||
565 | 566 | ||
566 | if (direction == DMA_TO_DEVICE) | 567 | if (direction == DMA_TO_DEVICE) |
567 | chan = host->write_dma_chan; | 568 | chan = host->write_dma_chan; |
@@ -601,14 +602,13 @@ static int dma_xfer(struct fsmc_nand_data *host, void *buffer, int len, | |||
601 | 602 | ||
602 | dma_async_issue_pending(chan); | 603 | dma_async_issue_pending(chan); |
603 | 604 | ||
604 | ret = | 605 | time_left = |
605 | wait_for_completion_timeout(&host->dma_access_complete, | 606 | wait_for_completion_timeout(&host->dma_access_complete, |
606 | msecs_to_jiffies(3000)); | 607 | msecs_to_jiffies(3000)); |
607 | if (ret <= 0) { | 608 | if (time_left == 0) { |
608 | dmaengine_terminate_all(chan); | 609 | dmaengine_terminate_all(chan); |
609 | dev_err(host->dev, "wait_for_completion_timeout\n"); | 610 | dev_err(host->dev, "wait_for_completion_timeout\n"); |
610 | if (!ret) | 611 | ret = -ETIMEDOUT; |
611 | ret = -ETIMEDOUT; | ||
612 | goto unmap_dma; | 612 | goto unmap_dma; |
613 | } | 613 | } |
614 | 614 | ||
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index 1f12e5bfbced..2a49b53c8db9 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c | |||
@@ -837,7 +837,7 @@ static int mpc5121_nfc_remove(struct platform_device *op) | |||
837 | return 0; | 837 | return 0; |
838 | } | 838 | } |
839 | 839 | ||
840 | static struct of_device_id mpc5121_nfc_match[] = { | 840 | static const struct of_device_id mpc5121_nfc_match[] = { |
841 | { .compatible = "fsl,mpc5121-nfc", }, | 841 | { .compatible = "fsl,mpc5121-nfc", }, |
842 | {}, | 842 | {}, |
843 | }; | 843 | }; |
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 372e0e38f59b..2426db88db36 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -189,6 +189,7 @@ struct mxc_nand_host { | |||
189 | int clk_act; | 189 | int clk_act; |
190 | int irq; | 190 | int irq; |
191 | int eccsize; | 191 | int eccsize; |
192 | int used_oobsize; | ||
192 | int active_cs; | 193 | int active_cs; |
193 | 194 | ||
194 | struct completion op_completion; | 195 | struct completion op_completion; |
@@ -280,12 +281,44 @@ static void memcpy32_fromio(void *trg, const void __iomem *src, size_t size) | |||
280 | *t++ = __raw_readl(s++); | 281 | *t++ = __raw_readl(s++); |
281 | } | 282 | } |
282 | 283 | ||
284 | static void memcpy16_fromio(void *trg, const void __iomem *src, size_t size) | ||
285 | { | ||
286 | int i; | ||
287 | u16 *t = trg; | ||
288 | const __iomem u16 *s = src; | ||
289 | |||
290 | /* We assume that src (IO) is always 32bit aligned */ | ||
291 | if (PTR_ALIGN(trg, 4) == trg && IS_ALIGNED(size, 4)) { | ||
292 | memcpy32_fromio(trg, src, size); | ||
293 | return; | ||
294 | } | ||
295 | |||
296 | for (i = 0; i < (size >> 1); i++) | ||
297 | *t++ = __raw_readw(s++); | ||
298 | } | ||
299 | |||
283 | static inline void memcpy32_toio(void __iomem *trg, const void *src, int size) | 300 | static inline void memcpy32_toio(void __iomem *trg, const void *src, int size) |
284 | { | 301 | { |
285 | /* __iowrite32_copy use 32bit size values so divide by 4 */ | 302 | /* __iowrite32_copy use 32bit size values so divide by 4 */ |
286 | __iowrite32_copy(trg, src, size / 4); | 303 | __iowrite32_copy(trg, src, size / 4); |
287 | } | 304 | } |
288 | 305 | ||
306 | static void memcpy16_toio(void __iomem *trg, const void *src, int size) | ||
307 | { | ||
308 | int i; | ||
309 | __iomem u16 *t = trg; | ||
310 | const u16 *s = src; | ||
311 | |||
312 | /* We assume that trg (IO) is always 32bit aligned */ | ||
313 | if (PTR_ALIGN(src, 4) == src && IS_ALIGNED(size, 4)) { | ||
314 | memcpy32_toio(trg, src, size); | ||
315 | return; | ||
316 | } | ||
317 | |||
318 | for (i = 0; i < (size >> 1); i++) | ||
319 | __raw_writew(*s++, t++); | ||
320 | } | ||
321 | |||
289 | static int check_int_v3(struct mxc_nand_host *host) | 322 | static int check_int_v3(struct mxc_nand_host *host) |
290 | { | 323 | { |
291 | uint32_t tmp; | 324 | uint32_t tmp; |
@@ -807,32 +840,48 @@ static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip) | |||
807 | } | 840 | } |
808 | 841 | ||
809 | /* | 842 | /* |
810 | * Function to transfer data to/from spare area. | 843 | * The controller splits a page into data chunks of 512 bytes + partial oob. |
844 | * There are writesize / 512 such chunks, the size of the partial oob parts is | ||
845 | * oobsize / #chunks rounded down to a multiple of 2. The last oob chunk then | ||
846 | * contains additionally the byte lost by rounding (if any). | ||
847 | * This function handles the needed shuffling between host->data_buf (which | ||
848 | * holds a page in natural order, i.e. writesize bytes data + oobsize bytes | ||
849 | * spare) and the NFC buffer. | ||
811 | */ | 850 | */ |
812 | static void copy_spare(struct mtd_info *mtd, bool bfrom) | 851 | static void copy_spare(struct mtd_info *mtd, bool bfrom) |
813 | { | 852 | { |
814 | struct nand_chip *this = mtd->priv; | 853 | struct nand_chip *this = mtd->priv; |
815 | struct mxc_nand_host *host = this->priv; | 854 | struct mxc_nand_host *host = this->priv; |
816 | u16 i, j; | 855 | u16 i, oob_chunk_size; |
817 | u16 n = mtd->writesize >> 9; | 856 | u16 num_chunks = mtd->writesize / 512; |
857 | |||
818 | u8 *d = host->data_buf + mtd->writesize; | 858 | u8 *d = host->data_buf + mtd->writesize; |
819 | u8 __iomem *s = host->spare0; | 859 | u8 __iomem *s = host->spare0; |
820 | u16 t = host->devtype_data->spare_len; | 860 | u16 sparebuf_size = host->devtype_data->spare_len; |
821 | 861 | ||
822 | j = (mtd->oobsize / n >> 1) << 1; | 862 | /* size of oob chunk for all but possibly the last one */ |
863 | oob_chunk_size = (host->used_oobsize / num_chunks) & ~1; | ||
823 | 864 | ||
824 | if (bfrom) { | 865 | if (bfrom) { |
825 | for (i = 0; i < n - 1; i++) | 866 | for (i = 0; i < num_chunks - 1; i++) |
826 | memcpy32_fromio(d + i * j, s + i * t, j); | 867 | memcpy16_fromio(d + i * oob_chunk_size, |
827 | 868 | s + i * sparebuf_size, | |
828 | /* the last section */ | 869 | oob_chunk_size); |
829 | memcpy32_fromio(d + i * j, s + i * t, mtd->oobsize - i * j); | 870 | |
871 | /* the last chunk */ | ||
872 | memcpy16_fromio(d + i * oob_chunk_size, | ||
873 | s + i * sparebuf_size, | ||
874 | host->used_oobsize - i * oob_chunk_size); | ||
830 | } else { | 875 | } else { |
831 | for (i = 0; i < n - 1; i++) | 876 | for (i = 0; i < num_chunks - 1; i++) |
832 | memcpy32_toio(&s[i * t], &d[i * j], j); | 877 | memcpy16_toio(&s[i * sparebuf_size], |
833 | 878 | &d[i * oob_chunk_size], | |
834 | /* the last section */ | 879 | oob_chunk_size); |
835 | memcpy32_toio(&s[i * t], &d[i * j], mtd->oobsize - i * j); | 880 | |
881 | /* the last chunk */ | ||
882 | memcpy16_toio(&s[oob_chunk_size * sparebuf_size], | ||
883 | &d[i * oob_chunk_size], | ||
884 | host->used_oobsize - i * oob_chunk_size); | ||
836 | } | 885 | } |
837 | } | 886 | } |
838 | 887 | ||
@@ -911,6 +960,23 @@ static int get_eccsize(struct mtd_info *mtd) | |||
911 | return 8; | 960 | return 8; |
912 | } | 961 | } |
913 | 962 | ||
963 | static void ecc_8bit_layout_4k(struct nand_ecclayout *layout) | ||
964 | { | ||
965 | int i, j; | ||
966 | |||
967 | layout->eccbytes = 8*18; | ||
968 | for (i = 0; i < 8; i++) | ||
969 | for (j = 0; j < 18; j++) | ||
970 | layout->eccpos[i*18 + j] = i*26 + j + 7; | ||
971 | |||
972 | layout->oobfree[0].offset = 2; | ||
973 | layout->oobfree[0].length = 4; | ||
974 | for (i = 1; i < 8; i++) { | ||
975 | layout->oobfree[i].offset = i*26; | ||
976 | layout->oobfree[i].length = 7; | ||
977 | } | ||
978 | } | ||
979 | |||
914 | static void preset_v1(struct mtd_info *mtd) | 980 | static void preset_v1(struct mtd_info *mtd) |
915 | { | 981 | { |
916 | struct nand_chip *nand_chip = mtd->priv; | 982 | struct nand_chip *nand_chip = mtd->priv; |
@@ -1350,7 +1416,7 @@ static inline int is_imx53_nfc(struct mxc_nand_host *host) | |||
1350 | return host->devtype_data == &imx53_nand_devtype_data; | 1416 | return host->devtype_data == &imx53_nand_devtype_data; |
1351 | } | 1417 | } |
1352 | 1418 | ||
1353 | static struct platform_device_id mxcnd_devtype[] = { | 1419 | static const struct platform_device_id mxcnd_devtype[] = { |
1354 | { | 1420 | { |
1355 | .name = "imx21-nand", | 1421 | .name = "imx21-nand", |
1356 | .driver_data = (kernel_ulong_t) &imx21_nand_devtype_data, | 1422 | .driver_data = (kernel_ulong_t) &imx21_nand_devtype_data, |
@@ -1587,8 +1653,20 @@ static int mxcnd_probe(struct platform_device *pdev) | |||
1587 | 1653 | ||
1588 | if (mtd->writesize == 2048) | 1654 | if (mtd->writesize == 2048) |
1589 | this->ecc.layout = host->devtype_data->ecclayout_2k; | 1655 | this->ecc.layout = host->devtype_data->ecclayout_2k; |
1590 | else if (mtd->writesize == 4096) | 1656 | else if (mtd->writesize == 4096) { |
1591 | this->ecc.layout = host->devtype_data->ecclayout_4k; | 1657 | this->ecc.layout = host->devtype_data->ecclayout_4k; |
1658 | if (get_eccsize(mtd) == 8) | ||
1659 | ecc_8bit_layout_4k(this->ecc.layout); | ||
1660 | } | ||
1661 | |||
1662 | /* | ||
1663 | * Experimentation shows that i.MX NFC can only handle up to 218 oob | ||
1664 | * bytes. Limit used_oobsize to 218 so as to not confuse copy_spare() | ||
1665 | * into copying invalid data to/from the spare IO buffer, as this | ||
1666 | * might cause ECC data corruption when doing sub-page write to a | ||
1667 | * partially written page. | ||
1668 | */ | ||
1669 | host->used_oobsize = min(mtd->oobsize, 218U); | ||
1592 | 1670 | ||
1593 | if (this->ecc.mode == NAND_ECC_HW) { | 1671 | if (this->ecc.mode == NAND_ECC_HW) { |
1594 | if (is_imx21_nfc(host) || is_imx27_nfc(host)) | 1672 | if (is_imx21_nfc(host) || is_imx27_nfc(host)) |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index c2e1232cd45c..ceb68ca8277a 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/mtd/nand.c | ||
3 | * | ||
4 | * Overview: | 2 | * Overview: |
5 | * This is the generic MTD driver for NAND flash devices. It should be | 3 | * This is the generic MTD driver for NAND flash devices. It should be |
6 | * capable of working with almost all NAND chips currently available. | 4 | * capable of working with almost all NAND chips currently available. |
@@ -48,6 +46,7 @@ | |||
48 | #include <linux/leds.h> | 46 | #include <linux/leds.h> |
49 | #include <linux/io.h> | 47 | #include <linux/io.h> |
50 | #include <linux/mtd/partitions.h> | 48 | #include <linux/mtd/partitions.h> |
49 | #include <linux/of_mtd.h> | ||
51 | 50 | ||
52 | /* Define default oob placement schemes for large and small page devices */ | 51 | /* Define default oob placement schemes for large and small page devices */ |
53 | static struct nand_ecclayout nand_oob_8 = { | 52 | static struct nand_ecclayout nand_oob_8 = { |
@@ -2928,9 +2927,6 @@ static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip, | |||
2928 | & ONFI_OPT_CMD_SET_GET_FEATURES)) | 2927 | & ONFI_OPT_CMD_SET_GET_FEATURES)) |
2929 | return -EINVAL; | 2928 | return -EINVAL; |
2930 | 2929 | ||
2931 | /* clear the sub feature parameters */ | ||
2932 | memset(subfeature_param, 0, ONFI_SUBFEATURE_PARAM_LEN); | ||
2933 | |||
2934 | chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1); | 2930 | chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1); |
2935 | for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) | 2931 | for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) |
2936 | *subfeature_param++ = chip->read_byte(mtd); | 2932 | *subfeature_param++ = chip->read_byte(mtd); |
@@ -3689,7 +3685,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
3689 | if (find_full_id_nand(mtd, chip, type, id_data, &busw)) | 3685 | if (find_full_id_nand(mtd, chip, type, id_data, &busw)) |
3690 | goto ident_done; | 3686 | goto ident_done; |
3691 | } else if (*dev_id == type->dev_id) { | 3687 | } else if (*dev_id == type->dev_id) { |
3692 | break; | 3688 | break; |
3693 | } | 3689 | } |
3694 | } | 3690 | } |
3695 | 3691 | ||
@@ -3798,6 +3794,39 @@ ident_done: | |||
3798 | return type; | 3794 | return type; |
3799 | } | 3795 | } |
3800 | 3796 | ||
3797 | static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip, | ||
3798 | struct device_node *dn) | ||
3799 | { | ||
3800 | int ecc_mode, ecc_strength, ecc_step; | ||
3801 | |||
3802 | if (of_get_nand_bus_width(dn) == 16) | ||
3803 | chip->options |= NAND_BUSWIDTH_16; | ||
3804 | |||
3805 | if (of_get_nand_on_flash_bbt(dn)) | ||
3806 | chip->bbt_options |= NAND_BBT_USE_FLASH; | ||
3807 | |||
3808 | ecc_mode = of_get_nand_ecc_mode(dn); | ||
3809 | ecc_strength = of_get_nand_ecc_strength(dn); | ||
3810 | ecc_step = of_get_nand_ecc_step_size(dn); | ||
3811 | |||
3812 | if ((ecc_step >= 0 && !(ecc_strength >= 0)) || | ||
3813 | (!(ecc_step >= 0) && ecc_strength >= 0)) { | ||
3814 | pr_err("must set both strength and step size in DT\n"); | ||
3815 | return -EINVAL; | ||
3816 | } | ||
3817 | |||
3818 | if (ecc_mode >= 0) | ||
3819 | chip->ecc.mode = ecc_mode; | ||
3820 | |||
3821 | if (ecc_strength >= 0) | ||
3822 | chip->ecc.strength = ecc_strength; | ||
3823 | |||
3824 | if (ecc_step > 0) | ||
3825 | chip->ecc.size = ecc_step; | ||
3826 | |||
3827 | return 0; | ||
3828 | } | ||
3829 | |||
3801 | /** | 3830 | /** |
3802 | * nand_scan_ident - [NAND Interface] Scan for the NAND device | 3831 | * nand_scan_ident - [NAND Interface] Scan for the NAND device |
3803 | * @mtd: MTD device structure | 3832 | * @mtd: MTD device structure |
@@ -3815,6 +3844,13 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, | |||
3815 | int i, nand_maf_id, nand_dev_id; | 3844 | int i, nand_maf_id, nand_dev_id; |
3816 | struct nand_chip *chip = mtd->priv; | 3845 | struct nand_chip *chip = mtd->priv; |
3817 | struct nand_flash_dev *type; | 3846 | struct nand_flash_dev *type; |
3847 | int ret; | ||
3848 | |||
3849 | if (chip->dn) { | ||
3850 | ret = nand_dt_init(mtd, chip, chip->dn); | ||
3851 | if (ret) | ||
3852 | return ret; | ||
3853 | } | ||
3818 | 3854 | ||
3819 | /* Set the default functions */ | 3855 | /* Set the default functions */ |
3820 | nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16); | 3856 | nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16); |
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 9bb8453d224e..63a1a36a3f4b 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/mtd/nand_bbt.c | ||
3 | * | ||
4 | * Overview: | 2 | * Overview: |
5 | * Bad block table support for the NAND driver | 3 | * Bad block table support for the NAND driver |
6 | * | 4 | * |
@@ -64,7 +62,6 @@ | |||
64 | #include <linux/mtd/mtd.h> | 62 | #include <linux/mtd/mtd.h> |
65 | #include <linux/mtd/bbm.h> | 63 | #include <linux/mtd/bbm.h> |
66 | #include <linux/mtd/nand.h> | 64 | #include <linux/mtd/nand.h> |
67 | #include <linux/mtd/nand_ecc.h> | ||
68 | #include <linux/bitops.h> | 65 | #include <linux/bitops.h> |
69 | #include <linux/delay.h> | 66 | #include <linux/delay.h> |
70 | #include <linux/vmalloc.h> | 67 | #include <linux/vmalloc.h> |
@@ -720,7 +717,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
720 | /* Must we save the block contents? */ | 717 | /* Must we save the block contents? */ |
721 | if (td->options & NAND_BBT_SAVECONTENT) { | 718 | if (td->options & NAND_BBT_SAVECONTENT) { |
722 | /* Make it block aligned */ | 719 | /* Make it block aligned */ |
723 | to &= ~((loff_t)((1 << this->bbt_erase_shift) - 1)); | 720 | to &= ~(((loff_t)1 << this->bbt_erase_shift) - 1); |
724 | len = 1 << this->bbt_erase_shift; | 721 | len = 1 << this->bbt_erase_shift; |
725 | res = mtd_read(mtd, to, len, &retlen, buf); | 722 | res = mtd_read(mtd, to, len, &retlen, buf); |
726 | if (res < 0) { | 723 | if (res < 0) { |
@@ -1075,10 +1072,10 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd) | |||
1075 | * The bad block table memory is allocated here. It must be freed by calling | 1072 | * The bad block table memory is allocated here. It must be freed by calling |
1076 | * the nand_free_bbt function. | 1073 | * the nand_free_bbt function. |
1077 | */ | 1074 | */ |
1078 | int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) | 1075 | static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) |
1079 | { | 1076 | { |
1080 | struct nand_chip *this = mtd->priv; | 1077 | struct nand_chip *this = mtd->priv; |
1081 | int len, res = 0; | 1078 | int len, res; |
1082 | uint8_t *buf; | 1079 | uint8_t *buf; |
1083 | struct nand_bbt_descr *td = this->bbt_td; | 1080 | struct nand_bbt_descr *td = this->bbt_td; |
1084 | struct nand_bbt_descr *md = this->bbt_md; | 1081 | struct nand_bbt_descr *md = this->bbt_md; |
@@ -1099,10 +1096,9 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) | |||
1099 | if (!td) { | 1096 | if (!td) { |
1100 | if ((res = nand_memory_bbt(mtd, bd))) { | 1097 | if ((res = nand_memory_bbt(mtd, bd))) { |
1101 | pr_err("nand_bbt: can't scan flash and build the RAM-based BBT\n"); | 1098 | pr_err("nand_bbt: can't scan flash and build the RAM-based BBT\n"); |
1102 | kfree(this->bbt); | 1099 | goto err; |
1103 | this->bbt = NULL; | ||
1104 | } | 1100 | } |
1105 | return res; | 1101 | return 0; |
1106 | } | 1102 | } |
1107 | verify_bbt_descr(mtd, td); | 1103 | verify_bbt_descr(mtd, td); |
1108 | verify_bbt_descr(mtd, md); | 1104 | verify_bbt_descr(mtd, md); |
@@ -1112,9 +1108,8 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) | |||
1112 | len += (len >> this->page_shift) * mtd->oobsize; | 1108 | len += (len >> this->page_shift) * mtd->oobsize; |
1113 | buf = vmalloc(len); | 1109 | buf = vmalloc(len); |
1114 | if (!buf) { | 1110 | if (!buf) { |
1115 | kfree(this->bbt); | 1111 | res = -ENOMEM; |
1116 | this->bbt = NULL; | 1112 | goto err; |
1117 | return -ENOMEM; | ||
1118 | } | 1113 | } |
1119 | 1114 | ||
1120 | /* Is the bbt at a given page? */ | 1115 | /* Is the bbt at a given page? */ |
@@ -1126,6 +1121,8 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) | |||
1126 | } | 1121 | } |
1127 | 1122 | ||
1128 | res = check_create(mtd, buf, bd); | 1123 | res = check_create(mtd, buf, bd); |
1124 | if (res) | ||
1125 | goto err; | ||
1129 | 1126 | ||
1130 | /* Prevent the bbt regions from erasing / writing */ | 1127 | /* Prevent the bbt regions from erasing / writing */ |
1131 | mark_bbt_region(mtd, td); | 1128 | mark_bbt_region(mtd, td); |
@@ -1133,6 +1130,11 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) | |||
1133 | mark_bbt_region(mtd, md); | 1130 | mark_bbt_region(mtd, md); |
1134 | 1131 | ||
1135 | vfree(buf); | 1132 | vfree(buf); |
1133 | return 0; | ||
1134 | |||
1135 | err: | ||
1136 | kfree(this->bbt); | ||
1137 | this->bbt = NULL; | ||
1136 | return res; | 1138 | return res; |
1137 | } | 1139 | } |
1138 | 1140 | ||
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index dd620c19c619..7124400d903b 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/mtd/nandids.c | ||
3 | * | ||
4 | * Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de) | 2 | * Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de) |
5 | * | 3 | * |
6 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index f2324271b94e..52c0c1a3899c 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
@@ -743,6 +743,11 @@ static int init_nandsim(struct mtd_info *mtd) | |||
743 | goto error; | 743 | goto error; |
744 | } | 744 | } |
745 | ns->partitions[i].name = get_partition_name(i); | 745 | ns->partitions[i].name = get_partition_name(i); |
746 | if (!ns->partitions[i].name) { | ||
747 | NS_ERR("unable to allocate memory.\n"); | ||
748 | ret = -ENOMEM; | ||
749 | goto error; | ||
750 | } | ||
746 | ns->partitions[i].offset = next_offset; | 751 | ns->partitions[i].offset = next_offset; |
747 | ns->partitions[i].size = part_sz; | 752 | ns->partitions[i].size = part_sz; |
748 | next_offset += ns->partitions[i].size; | 753 | next_offset += ns->partitions[i].size; |
@@ -756,6 +761,11 @@ static int init_nandsim(struct mtd_info *mtd) | |||
756 | goto error; | 761 | goto error; |
757 | } | 762 | } |
758 | ns->partitions[i].name = get_partition_name(i); | 763 | ns->partitions[i].name = get_partition_name(i); |
764 | if (!ns->partitions[i].name) { | ||
765 | NS_ERR("unable to allocate memory.\n"); | ||
766 | ret = -ENOMEM; | ||
767 | goto error; | ||
768 | } | ||
759 | ns->partitions[i].offset = next_offset; | 769 | ns->partitions[i].offset = next_offset; |
760 | ns->partitions[i].size = remains; | 770 | ns->partitions[i].size = remains; |
761 | ns->nbparts += 1; | 771 | ns->nbparts += 1; |
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 3187c6b92d9a..67a1b3f911cf 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/mtd/ndfc.c | ||
3 | * | ||
4 | * Overview: | 2 | * Overview: |
5 | * Platform independent driver for NDFC (NanD Flash Controller) | 3 | * Platform independent driver for NDFC (NanD Flash Controller) |
6 | * integrated into EP440 cores | 4 | * integrated into EP440 cores |
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index 4535c263fae5..717cf623fcde 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c | |||
@@ -24,8 +24,6 @@ struct plat_nand_data { | |||
24 | void __iomem *io_base; | 24 | void __iomem *io_base; |
25 | }; | 25 | }; |
26 | 26 | ||
27 | static const char *part_probe_types[] = { "cmdlinepart", NULL }; | ||
28 | |||
29 | /* | 27 | /* |
30 | * Probe for the NAND device. | 28 | * Probe for the NAND device. |
31 | */ | 29 | */ |
@@ -95,7 +93,7 @@ static int plat_nand_probe(struct platform_device *pdev) | |||
95 | goto out; | 93 | goto out; |
96 | } | 94 | } |
97 | 95 | ||
98 | part_types = pdata->chip.part_probe_types ? : part_probe_types; | 96 | part_types = pdata->chip.part_probe_types; |
99 | 97 | ||
100 | ppdata.of_node = pdev->dev.of_node; | 98 | ppdata.of_node = pdev->dev.of_node; |
101 | err = mtd_device_parse_register(&data->mtd, part_types, &ppdata, | 99 | err = mtd_device_parse_register(&data->mtd, part_types, &ppdata, |
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index a4615fcc3d00..1259cc558ce9 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
@@ -22,13 +22,14 @@ | |||
22 | #include <linux/mtd/nand.h> | 22 | #include <linux/mtd/nand.h> |
23 | #include <linux/mtd/partitions.h> | 23 | #include <linux/mtd/partitions.h> |
24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
25 | #include <linux/iopoll.h> | ||
25 | #include <linux/irq.h> | 26 | #include <linux/irq.h> |
26 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
27 | #include <linux/of.h> | 28 | #include <linux/of.h> |
28 | #include <linux/of_device.h> | 29 | #include <linux/of_device.h> |
29 | #include <linux/of_mtd.h> | 30 | #include <linux/of_mtd.h> |
30 | 31 | ||
31 | #if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP) | 32 | #if defined(CONFIG_ARM) && (defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP)) |
32 | #define ARCH_HAS_DMA | 33 | #define ARCH_HAS_DMA |
33 | #endif | 34 | #endif |
34 | 35 | ||
@@ -483,7 +484,8 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) | |||
483 | static void drain_fifo(struct pxa3xx_nand_info *info, void *data, int len) | 484 | static void drain_fifo(struct pxa3xx_nand_info *info, void *data, int len) |
484 | { | 485 | { |
485 | if (info->ecc_bch) { | 486 | if (info->ecc_bch) { |
486 | int timeout; | 487 | u32 val; |
488 | int ret; | ||
487 | 489 | ||
488 | /* | 490 | /* |
489 | * According to the datasheet, when reading from NDDB | 491 | * According to the datasheet, when reading from NDDB |
@@ -494,18 +496,14 @@ static void drain_fifo(struct pxa3xx_nand_info *info, void *data, int len) | |||
494 | * the polling on the last read. | 496 | * the polling on the last read. |
495 | */ | 497 | */ |
496 | while (len > 8) { | 498 | while (len > 8) { |
497 | __raw_readsl(info->mmio_base + NDDB, data, 8); | 499 | readsl(info->mmio_base + NDDB, data, 8); |
498 | 500 | ||
499 | for (timeout = 0; | 501 | ret = readl_relaxed_poll_timeout(info->mmio_base + NDSR, val, |
500 | !(nand_readl(info, NDSR) & NDSR_RDDREQ); | 502 | val & NDSR_RDDREQ, 1000, 5000); |
501 | timeout++) { | 503 | if (ret) { |
502 | if (timeout >= 5) { | 504 | dev_err(&info->pdev->dev, |
503 | dev_err(&info->pdev->dev, | 505 | "Timeout on RDDREQ while draining the FIFO\n"); |
504 | "Timeout on RDDREQ while draining the FIFO\n"); | 506 | return; |
505 | return; | ||
506 | } | ||
507 | |||
508 | mdelay(1); | ||
509 | } | 507 | } |
510 | 508 | ||
511 | data += 32; | 509 | data += 32; |
@@ -513,7 +511,7 @@ static void drain_fifo(struct pxa3xx_nand_info *info, void *data, int len) | |||
513 | } | 511 | } |
514 | } | 512 | } |
515 | 513 | ||
516 | __raw_readsl(info->mmio_base + NDDB, data, len); | 514 | readsl(info->mmio_base + NDDB, data, len); |
517 | } | 515 | } |
518 | 516 | ||
519 | static void handle_data_pio(struct pxa3xx_nand_info *info) | 517 | static void handle_data_pio(struct pxa3xx_nand_info *info) |
@@ -522,14 +520,14 @@ static void handle_data_pio(struct pxa3xx_nand_info *info) | |||
522 | 520 | ||
523 | switch (info->state) { | 521 | switch (info->state) { |
524 | case STATE_PIO_WRITING: | 522 | case STATE_PIO_WRITING: |
525 | __raw_writesl(info->mmio_base + NDDB, | 523 | writesl(info->mmio_base + NDDB, |
526 | info->data_buff + info->data_buff_pos, | 524 | info->data_buff + info->data_buff_pos, |
527 | DIV_ROUND_UP(do_bytes, 4)); | 525 | DIV_ROUND_UP(do_bytes, 4)); |
528 | 526 | ||
529 | if (info->oob_size > 0) | 527 | if (info->oob_size > 0) |
530 | __raw_writesl(info->mmio_base + NDDB, | 528 | writesl(info->mmio_base + NDDB, |
531 | info->oob_buff + info->oob_buff_pos, | 529 | info->oob_buff + info->oob_buff_pos, |
532 | DIV_ROUND_UP(info->oob_size, 4)); | 530 | DIV_ROUND_UP(info->oob_size, 4)); |
533 | break; | 531 | break; |
534 | case STATE_PIO_READING: | 532 | case STATE_PIO_READING: |
535 | drain_fifo(info, | 533 | drain_fifo(info, |
@@ -1630,8 +1628,7 @@ static int alloc_nand_resource(struct platform_device *pdev) | |||
1630 | info->pdev = pdev; | 1628 | info->pdev = pdev; |
1631 | info->variant = pxa3xx_nand_get_variant(pdev); | 1629 | info->variant = pxa3xx_nand_get_variant(pdev); |
1632 | for (cs = 0; cs < pdata->num_cs; cs++) { | 1630 | for (cs = 0; cs < pdata->num_cs; cs++) { |
1633 | mtd = (struct mtd_info *)((unsigned int)&info[1] + | 1631 | mtd = (void *)&info[1] + (sizeof(*mtd) + sizeof(*host)) * cs; |
1634 | (sizeof(*mtd) + sizeof(*host)) * cs); | ||
1635 | chip = (struct nand_chip *)(&mtd[1]); | 1632 | chip = (struct nand_chip *)(&mtd[1]); |
1636 | host = (struct pxa3xx_nand_host *)chip; | 1633 | host = (struct pxa3xx_nand_host *)chip; |
1637 | info->host[cs] = host; | 1634 | info->host[cs] = host; |
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index baea83f4dea8..77e96d2df96c 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c | |||
@@ -653,11 +653,15 @@ static int r852_register_nand_device(struct r852_device *dev) | |||
653 | if (sm_register_device(dev->mtd, dev->sm)) | 653 | if (sm_register_device(dev->mtd, dev->sm)) |
654 | goto error2; | 654 | goto error2; |
655 | 655 | ||
656 | if (device_create_file(&dev->mtd->dev, &dev_attr_media_type)) | 656 | if (device_create_file(&dev->mtd->dev, &dev_attr_media_type)) { |
657 | message("can't create media type sysfs attribute"); | 657 | message("can't create media type sysfs attribute"); |
658 | goto error3; | ||
659 | } | ||
658 | 660 | ||
659 | dev->card_registred = 1; | 661 | dev->card_registred = 1; |
660 | return 0; | 662 | return 0; |
663 | error3: | ||
664 | nand_release(dev->mtd); | ||
661 | error2: | 665 | error2: |
662 | kfree(dev->mtd); | 666 | kfree(dev->mtd); |
663 | error1: | 667 | error1: |
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 0e02be47ce1d..381f67ac6b5a 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c | |||
@@ -1105,7 +1105,7 @@ static int s3c24xx_nand_resume(struct platform_device *dev) | |||
1105 | 1105 | ||
1106 | /* driver device registration */ | 1106 | /* driver device registration */ |
1107 | 1107 | ||
1108 | static struct platform_device_id s3c24xx_driver_ids[] = { | 1108 | static const struct platform_device_id s3c24xx_driver_ids[] = { |
1109 | { | 1109 | { |
1110 | .name = "s3c2410-nand", | 1110 | .name = "s3c2410-nand", |
1111 | .driver_data = TYPE_S3C2410, | 1111 | .driver_data = TYPE_S3C2410, |
diff --git a/drivers/mtd/nand/xway_nand.c b/drivers/mtd/nand/xway_nand.c index 3f81dc8f214c..3b28db458ea0 100644 --- a/drivers/mtd/nand/xway_nand.c +++ b/drivers/mtd/nand/xway_nand.c | |||
@@ -160,14 +160,10 @@ static int xway_nand_probe(struct platform_device *pdev) | |||
160 | return 0; | 160 | return 0; |
161 | } | 161 | } |
162 | 162 | ||
163 | /* allow users to override the partition in DT using the cmdline */ | ||
164 | static const char *part_probes[] = { "cmdlinepart", "ofpart", NULL }; | ||
165 | |||
166 | static struct platform_nand_data xway_nand_data = { | 163 | static struct platform_nand_data xway_nand_data = { |
167 | .chip = { | 164 | .chip = { |
168 | .nr_chips = 1, | 165 | .nr_chips = 1, |
169 | .chip_delay = 30, | 166 | .chip_delay = 30, |
170 | .part_probe_types = part_probes, | ||
171 | }, | 167 | }, |
172 | .ctrl = { | 168 | .ctrl = { |
173 | .probe = xway_nand_probe, | 169 | .probe = xway_nand_probe, |
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index 19cfb97adbc0..739259513055 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c | |||
@@ -1083,7 +1083,7 @@ static const struct dev_pm_ops s3c_pm_ops = { | |||
1083 | .resume = s3c_pm_ops_resume, | 1083 | .resume = s3c_pm_ops_resume, |
1084 | }; | 1084 | }; |
1085 | 1085 | ||
1086 | static struct platform_device_id s3c_onenand_driver_ids[] = { | 1086 | static const struct platform_device_id s3c_onenand_driver_ids[] = { |
1087 | { | 1087 | { |
1088 | .name = "s3c6400-onenand", | 1088 | .name = "s3c6400-onenand", |
1089 | .driver_data = TYPE_S3C6400, | 1089 | .driver_data = TYPE_S3C6400, |
diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c index 5d5d36272bb5..52a872fa1b6e 100644 --- a/drivers/mtd/spi-nor/fsl-quadspi.c +++ b/drivers/mtd/spi-nor/fsl-quadspi.c | |||
@@ -662,7 +662,7 @@ static int fsl_qspi_nor_setup_last(struct fsl_qspi *q) | |||
662 | return 0; | 662 | return 0; |
663 | } | 663 | } |
664 | 664 | ||
665 | static struct of_device_id fsl_qspi_dt_ids[] = { | 665 | static const struct of_device_id fsl_qspi_dt_ids[] = { |
666 | { .compatible = "fsl,vf610-qspi", .data = (void *)&vybrid_data, }, | 666 | { .compatible = "fsl,vf610-qspi", .data = (void *)&vybrid_data, }, |
667 | { .compatible = "fsl,imx6sx-qspi", .data = (void *)&imx6sx_data, }, | 667 | { .compatible = "fsl,imx6sx-qspi", .data = (void *)&imx6sx_data, }, |
668 | { /* sentinel */ } | 668 | { /* sentinel */ } |
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 14a5d2325dac..d78831b4422b 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c | |||
@@ -513,6 +513,13 @@ static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
513 | /* NOTE: double check command sets and memory organization when you add | 513 | /* NOTE: double check command sets and memory organization when you add |
514 | * more nor chips. This current list focusses on newer chips, which | 514 | * more nor chips. This current list focusses on newer chips, which |
515 | * have been converging on command sets which including JEDEC ID. | 515 | * have been converging on command sets which including JEDEC ID. |
516 | * | ||
517 | * All newly added entries should describe *hardware* and should use SECT_4K | ||
518 | * (or SECT_4K_PMC) if hardware supports erasing 4 KiB sectors. For usage | ||
519 | * scenarios excluding small sectors there is config option that can be | ||
520 | * disabled: CONFIG_MTD_SPI_NOR_USE_4K_SECTORS. | ||
521 | * For historical (and compatibility) reasons (before we got above config) some | ||
522 | * old entries may be missing 4K flag. | ||
516 | */ | 523 | */ |
517 | static const struct spi_device_id spi_nor_ids[] = { | 524 | static const struct spi_device_id spi_nor_ids[] = { |
518 | /* Atmel -- some are (confusingly) marketed as "DataFlash" */ | 525 | /* Atmel -- some are (confusingly) marketed as "DataFlash" */ |
@@ -538,7 +545,7 @@ static const struct spi_device_id spi_nor_ids[] = { | |||
538 | { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, | 545 | { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, |
539 | { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) }, | 546 | { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) }, |
540 | { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) }, | 547 | { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) }, |
541 | { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, 0) }, | 548 | { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, SECT_4K) }, |
542 | 549 | ||
543 | /* ESMT */ | 550 | /* ESMT */ |
544 | { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K) }, | 551 | { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K) }, |
@@ -560,7 +567,11 @@ static const struct spi_device_id spi_nor_ids[] = { | |||
560 | { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) }, | 567 | { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) }, |
561 | { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) }, | 568 | { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) }, |
562 | 569 | ||
570 | /* ISSI */ | ||
571 | { "is25cd512", INFO(0x7f9d20, 0, 32 * 1024, 2, SECT_4K) }, | ||
572 | |||
563 | /* Macronix */ | 573 | /* Macronix */ |
574 | { "mx25l512e", INFO(0xc22010, 0, 64 * 1024, 1, SECT_4K) }, | ||
564 | { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) }, | 575 | { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) }, |
565 | { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, | 576 | { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, |
566 | { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, | 577 | { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, |
@@ -602,7 +613,7 @@ static const struct spi_device_id spi_nor_ids[] = { | |||
602 | { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, | 613 | { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, |
603 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, | 614 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, |
604 | { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, | 615 | { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, |
605 | { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, | 616 | { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) }, |
606 | { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, | 617 | { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, |
607 | { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) }, | 618 | { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) }, |
608 | { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) }, | 619 | { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) }, |
@@ -613,7 +624,8 @@ static const struct spi_device_id spi_nor_ids[] = { | |||
613 | { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, | 624 | { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, |
614 | { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) }, | 625 | { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) }, |
615 | { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, | 626 | { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, |
616 | { "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64, 0) }, | 627 | { "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64, SECT_4K) }, |
628 | { "s25fl164k", INFO(0x014017, 0, 64 * 1024, 128, SECT_4K) }, | ||
617 | 629 | ||
618 | /* SST -- large erase sizes are "overlays", "sectors" are 4K */ | 630 | /* SST -- large erase sizes are "overlays", "sectors" are 4K */ |
619 | { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, | 631 | { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, |
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 60d86e8fba6e..2caf1682036d 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c | |||
@@ -272,12 +272,9 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino) | |||
272 | mutex_lock(&f->sem); | 272 | mutex_lock(&f->sem); |
273 | 273 | ||
274 | ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); | 274 | ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); |
275 | if (ret) | ||
276 | goto error; | ||
275 | 277 | ||
276 | if (ret) { | ||
277 | mutex_unlock(&f->sem); | ||
278 | iget_failed(inode); | ||
279 | return ERR_PTR(ret); | ||
280 | } | ||
281 | inode->i_mode = jemode_to_cpu(latest_node.mode); | 278 | inode->i_mode = jemode_to_cpu(latest_node.mode); |
282 | i_uid_write(inode, je16_to_cpu(latest_node.uid)); | 279 | i_uid_write(inode, je16_to_cpu(latest_node.uid)); |
283 | i_gid_write(inode, je16_to_cpu(latest_node.gid)); | 280 | i_gid_write(inode, je16_to_cpu(latest_node.gid)); |
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index dddbde4f56f4..28e0aab42bc3 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c | |||
@@ -1203,17 +1203,13 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
1203 | JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n", | 1203 | JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n", |
1204 | ret, retlen, sizeof(*latest_node)); | 1204 | ret, retlen, sizeof(*latest_node)); |
1205 | /* FIXME: If this fails, there seems to be a memory leak. Find it. */ | 1205 | /* FIXME: If this fails, there seems to be a memory leak. Find it. */ |
1206 | mutex_unlock(&f->sem); | 1206 | return ret ? ret : -EIO; |
1207 | jffs2_do_clear_inode(c, f); | ||
1208 | return ret?ret:-EIO; | ||
1209 | } | 1207 | } |
1210 | 1208 | ||
1211 | crc = crc32(0, latest_node, sizeof(*latest_node)-8); | 1209 | crc = crc32(0, latest_node, sizeof(*latest_node)-8); |
1212 | if (crc != je32_to_cpu(latest_node->node_crc)) { | 1210 | if (crc != je32_to_cpu(latest_node->node_crc)) { |
1213 | JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n", | 1211 | JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n", |
1214 | f->inocache->ino, ref_offset(rii.latest_ref)); | 1212 | f->inocache->ino, ref_offset(rii.latest_ref)); |
1215 | mutex_unlock(&f->sem); | ||
1216 | jffs2_do_clear_inode(c, f); | ||
1217 | return -EIO; | 1213 | return -EIO; |
1218 | } | 1214 | } |
1219 | 1215 | ||
@@ -1250,16 +1246,11 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
1250 | * keep in RAM to facilitate quick follow symlink | 1246 | * keep in RAM to facilitate quick follow symlink |
1251 | * operation. */ | 1247 | * operation. */ |
1252 | uint32_t csize = je32_to_cpu(latest_node->csize); | 1248 | uint32_t csize = je32_to_cpu(latest_node->csize); |
1253 | if (csize > JFFS2_MAX_NAME_LEN) { | 1249 | if (csize > JFFS2_MAX_NAME_LEN) |
1254 | mutex_unlock(&f->sem); | ||
1255 | jffs2_do_clear_inode(c, f); | ||
1256 | return -ENAMETOOLONG; | 1250 | return -ENAMETOOLONG; |
1257 | } | ||
1258 | f->target = kmalloc(csize + 1, GFP_KERNEL); | 1251 | f->target = kmalloc(csize + 1, GFP_KERNEL); |
1259 | if (!f->target) { | 1252 | if (!f->target) { |
1260 | JFFS2_ERROR("can't allocate %u bytes of memory for the symlink target path cache\n", csize); | 1253 | JFFS2_ERROR("can't allocate %u bytes of memory for the symlink target path cache\n", csize); |
1261 | mutex_unlock(&f->sem); | ||
1262 | jffs2_do_clear_inode(c, f); | ||
1263 | return -ENOMEM; | 1254 | return -ENOMEM; |
1264 | } | 1255 | } |
1265 | 1256 | ||
@@ -1271,8 +1262,6 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
1271 | ret = -EIO; | 1262 | ret = -EIO; |
1272 | kfree(f->target); | 1263 | kfree(f->target); |
1273 | f->target = NULL; | 1264 | f->target = NULL; |
1274 | mutex_unlock(&f->sem); | ||
1275 | jffs2_do_clear_inode(c, f); | ||
1276 | return ret; | 1265 | return ret; |
1277 | } | 1266 | } |
1278 | 1267 | ||
@@ -1289,15 +1278,11 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
1289 | if (f->metadata) { | 1278 | if (f->metadata) { |
1290 | JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node\n", | 1279 | JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node\n", |
1291 | f->inocache->ino, jemode_to_cpu(latest_node->mode)); | 1280 | f->inocache->ino, jemode_to_cpu(latest_node->mode)); |
1292 | mutex_unlock(&f->sem); | ||
1293 | jffs2_do_clear_inode(c, f); | ||
1294 | return -EIO; | 1281 | return -EIO; |
1295 | } | 1282 | } |
1296 | if (!frag_first(&f->fragtree)) { | 1283 | if (!frag_first(&f->fragtree)) { |
1297 | JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments\n", | 1284 | JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments\n", |
1298 | f->inocache->ino, jemode_to_cpu(latest_node->mode)); | 1285 | f->inocache->ino, jemode_to_cpu(latest_node->mode)); |
1299 | mutex_unlock(&f->sem); | ||
1300 | jffs2_do_clear_inode(c, f); | ||
1301 | return -EIO; | 1286 | return -EIO; |
1302 | } | 1287 | } |
1303 | /* ASSERT: f->fraglist != NULL */ | 1288 | /* ASSERT: f->fraglist != NULL */ |
@@ -1305,8 +1290,6 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
1305 | JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node\n", | 1290 | JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node\n", |
1306 | f->inocache->ino, jemode_to_cpu(latest_node->mode)); | 1291 | f->inocache->ino, jemode_to_cpu(latest_node->mode)); |
1307 | /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */ | 1292 | /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */ |
1308 | mutex_unlock(&f->sem); | ||
1309 | jffs2_do_clear_inode(c, f); | ||
1310 | return -EIO; | 1293 | return -EIO; |
1311 | } | 1294 | } |
1312 | /* OK. We're happy */ | 1295 | /* OK. We're happy */ |
@@ -1400,10 +1383,8 @@ int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i | |||
1400 | f->inocache = ic; | 1383 | f->inocache = ic; |
1401 | 1384 | ||
1402 | ret = jffs2_do_read_inode_internal(c, f, &n); | 1385 | ret = jffs2_do_read_inode_internal(c, f, &n); |
1403 | if (!ret) { | 1386 | mutex_unlock(&f->sem); |
1404 | mutex_unlock(&f->sem); | 1387 | jffs2_do_clear_inode(c, f); |
1405 | jffs2_do_clear_inode(c, f); | ||
1406 | } | ||
1407 | jffs2_xattr_do_crccheck_inode(c, ic); | 1388 | jffs2_xattr_do_crccheck_inode(c, ic); |
1408 | kfree (f); | 1389 | kfree (f); |
1409 | return ret; | 1390 | return ret; |
diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index 299d7d31fe53..9b57a9b1b081 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h | |||
@@ -296,183 +296,19 @@ struct cfi_private { | |||
296 | struct flchip chips[0]; /* per-chip data structure for each chip */ | 296 | struct flchip chips[0]; /* per-chip data structure for each chip */ |
297 | }; | 297 | }; |
298 | 298 | ||
299 | /* | 299 | uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, |
300 | * Returns the command address according to the given geometry. | 300 | struct map_info *map, struct cfi_private *cfi); |
301 | */ | ||
302 | static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, | ||
303 | struct map_info *map, struct cfi_private *cfi) | ||
304 | { | ||
305 | unsigned bankwidth = map_bankwidth(map); | ||
306 | unsigned interleave = cfi_interleave(cfi); | ||
307 | unsigned type = cfi->device_type; | ||
308 | uint32_t addr; | ||
309 | |||
310 | addr = (cmd_ofs * type) * interleave; | ||
311 | |||
312 | /* Modify the unlock address if we are in compatibility mode. | ||
313 | * For 16bit devices on 8 bit busses | ||
314 | * and 32bit devices on 16 bit busses | ||
315 | * set the low bit of the alternating bit sequence of the address. | ||
316 | */ | ||
317 | if (((type * interleave) > bankwidth) && ((cmd_ofs & 0xff) == 0xaa)) | ||
318 | addr |= (type >> 1)*interleave; | ||
319 | |||
320 | return addr; | ||
321 | } | ||
322 | |||
323 | /* | ||
324 | * Transforms the CFI command for the given geometry (bus width & interleave). | ||
325 | * It looks too long to be inline, but in the common case it should almost all | ||
326 | * get optimised away. | ||
327 | */ | ||
328 | static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cfi_private *cfi) | ||
329 | { | ||
330 | map_word val = { {0} }; | ||
331 | int wordwidth, words_per_bus, chip_mode, chips_per_word; | ||
332 | unsigned long onecmd; | ||
333 | int i; | ||
334 | |||
335 | /* We do it this way to give the compiler a fighting chance | ||
336 | of optimising away all the crap for 'bankwidth' larger than | ||
337 | an unsigned long, in the common case where that support is | ||
338 | disabled */ | ||
339 | if (map_bankwidth_is_large(map)) { | ||
340 | wordwidth = sizeof(unsigned long); | ||
341 | words_per_bus = (map_bankwidth(map)) / wordwidth; // i.e. normally 1 | ||
342 | } else { | ||
343 | wordwidth = map_bankwidth(map); | ||
344 | words_per_bus = 1; | ||
345 | } | ||
346 | |||
347 | chip_mode = map_bankwidth(map) / cfi_interleave(cfi); | ||
348 | chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map); | ||
349 | |||
350 | /* First, determine what the bit-pattern should be for a single | ||
351 | device, according to chip mode and endianness... */ | ||
352 | switch (chip_mode) { | ||
353 | default: BUG(); | ||
354 | case 1: | ||
355 | onecmd = cmd; | ||
356 | break; | ||
357 | case 2: | ||
358 | onecmd = cpu_to_cfi16(map, cmd); | ||
359 | break; | ||
360 | case 4: | ||
361 | onecmd = cpu_to_cfi32(map, cmd); | ||
362 | break; | ||
363 | } | ||
364 | |||
365 | /* Now replicate it across the size of an unsigned long, or | ||
366 | just to the bus width as appropriate */ | ||
367 | switch (chips_per_word) { | ||
368 | default: BUG(); | ||
369 | #if BITS_PER_LONG >= 64 | ||
370 | case 8: | ||
371 | onecmd |= (onecmd << (chip_mode * 32)); | ||
372 | #endif | ||
373 | case 4: | ||
374 | onecmd |= (onecmd << (chip_mode * 16)); | ||
375 | case 2: | ||
376 | onecmd |= (onecmd << (chip_mode * 8)); | ||
377 | case 1: | ||
378 | ; | ||
379 | } | ||
380 | 301 | ||
381 | /* And finally, for the multi-word case, replicate it | 302 | map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cfi_private *cfi); |
382 | in all words in the structure */ | ||
383 | for (i=0; i < words_per_bus; i++) { | ||
384 | val.x[i] = onecmd; | ||
385 | } | ||
386 | |||
387 | return val; | ||
388 | } | ||
389 | #define CMD(x) cfi_build_cmd((x), map, cfi) | 303 | #define CMD(x) cfi_build_cmd((x), map, cfi) |
390 | 304 | ||
391 | 305 | unsigned long cfi_merge_status(map_word val, struct map_info *map, | |
392 | static inline unsigned long cfi_merge_status(map_word val, struct map_info *map, | 306 | struct cfi_private *cfi); |
393 | struct cfi_private *cfi) | ||
394 | { | ||
395 | int wordwidth, words_per_bus, chip_mode, chips_per_word; | ||
396 | unsigned long onestat, res = 0; | ||
397 | int i; | ||
398 | |||
399 | /* We do it this way to give the compiler a fighting chance | ||
400 | of optimising away all the crap for 'bankwidth' larger than | ||
401 | an unsigned long, in the common case where that support is | ||
402 | disabled */ | ||
403 | if (map_bankwidth_is_large(map)) { | ||
404 | wordwidth = sizeof(unsigned long); | ||
405 | words_per_bus = (map_bankwidth(map)) / wordwidth; // i.e. normally 1 | ||
406 | } else { | ||
407 | wordwidth = map_bankwidth(map); | ||
408 | words_per_bus = 1; | ||
409 | } | ||
410 | |||
411 | chip_mode = map_bankwidth(map) / cfi_interleave(cfi); | ||
412 | chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map); | ||
413 | |||
414 | onestat = val.x[0]; | ||
415 | /* Or all status words together */ | ||
416 | for (i=1; i < words_per_bus; i++) { | ||
417 | onestat |= val.x[i]; | ||
418 | } | ||
419 | |||
420 | res = onestat; | ||
421 | switch(chips_per_word) { | ||
422 | default: BUG(); | ||
423 | #if BITS_PER_LONG >= 64 | ||
424 | case 8: | ||
425 | res |= (onestat >> (chip_mode * 32)); | ||
426 | #endif | ||
427 | case 4: | ||
428 | res |= (onestat >> (chip_mode * 16)); | ||
429 | case 2: | ||
430 | res |= (onestat >> (chip_mode * 8)); | ||
431 | case 1: | ||
432 | ; | ||
433 | } | ||
434 | |||
435 | /* Last, determine what the bit-pattern should be for a single | ||
436 | device, according to chip mode and endianness... */ | ||
437 | switch (chip_mode) { | ||
438 | case 1: | ||
439 | break; | ||
440 | case 2: | ||
441 | res = cfi16_to_cpu(map, res); | ||
442 | break; | ||
443 | case 4: | ||
444 | res = cfi32_to_cpu(map, res); | ||
445 | break; | ||
446 | default: BUG(); | ||
447 | } | ||
448 | return res; | ||
449 | } | ||
450 | |||
451 | #define MERGESTATUS(x) cfi_merge_status((x), map, cfi) | 307 | #define MERGESTATUS(x) cfi_merge_status((x), map, cfi) |
452 | 308 | ||
453 | 309 | uint32_t cfi_send_gen_cmd(u_char cmd, uint32_t cmd_addr, uint32_t base, | |
454 | /* | ||
455 | * Sends a CFI command to a bank of flash for the given geometry. | ||
456 | * | ||
457 | * Returns the offset in flash where the command was written. | ||
458 | * If prev_val is non-null, it will be set to the value at the command address, | ||
459 | * before the command was written. | ||
460 | */ | ||
461 | static inline uint32_t cfi_send_gen_cmd(u_char cmd, uint32_t cmd_addr, uint32_t base, | ||
462 | struct map_info *map, struct cfi_private *cfi, | 310 | struct map_info *map, struct cfi_private *cfi, |
463 | int type, map_word *prev_val) | 311 | int type, map_word *prev_val); |
464 | { | ||
465 | map_word val; | ||
466 | uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, map, cfi); | ||
467 | val = cfi_build_cmd(cmd, map, cfi); | ||
468 | |||
469 | if (prev_val) | ||
470 | *prev_val = map_read(map, addr); | ||
471 | |||
472 | map_write(map, val, addr); | ||
473 | |||
474 | return addr - base; | ||
475 | } | ||
476 | 312 | ||
477 | static inline uint8_t cfi_read_query(struct map_info *map, uint32_t addr) | 313 | static inline uint8_t cfi_read_query(struct map_info *map, uint32_t addr) |
478 | { | 314 | { |
@@ -506,15 +342,7 @@ static inline uint16_t cfi_read_query16(struct map_info *map, uint32_t addr) | |||
506 | } | 342 | } |
507 | } | 343 | } |
508 | 344 | ||
509 | static inline void cfi_udelay(int us) | 345 | void cfi_udelay(int us); |
510 | { | ||
511 | if (us >= 1000) { | ||
512 | msleep((us+999)/1000); | ||
513 | } else { | ||
514 | udelay(us); | ||
515 | cond_resched(); | ||
516 | } | ||
517 | } | ||
518 | 346 | ||
519 | int __xipram cfi_qry_present(struct map_info *map, __u32 base, | 347 | int __xipram cfi_qry_present(struct map_info *map, __u32 base, |
520 | struct cfi_private *cfi); | 348 | struct cfi_private *cfi); |
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 3d4ea7eb2b68..f25e2bdd188c 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h | |||
@@ -26,6 +26,8 @@ | |||
26 | 26 | ||
27 | struct mtd_info; | 27 | struct mtd_info; |
28 | struct nand_flash_dev; | 28 | struct nand_flash_dev; |
29 | struct device_node; | ||
30 | |||
29 | /* Scan and identify a NAND device */ | 31 | /* Scan and identify a NAND device */ |
30 | extern int nand_scan(struct mtd_info *mtd, int max_chips); | 32 | extern int nand_scan(struct mtd_info *mtd, int max_chips); |
31 | /* | 33 | /* |
@@ -542,6 +544,7 @@ struct nand_buffers { | |||
542 | * flash device | 544 | * flash device |
543 | * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the | 545 | * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the |
544 | * flash device. | 546 | * flash device. |
547 | * @dn: [BOARDSPECIFIC] device node describing this instance | ||
545 | * @read_byte: [REPLACEABLE] read one byte from the chip | 548 | * @read_byte: [REPLACEABLE] read one byte from the chip |
546 | * @read_word: [REPLACEABLE] read one word from the chip | 549 | * @read_word: [REPLACEABLE] read one word from the chip |
547 | * @write_byte: [REPLACEABLE] write a single byte to the chip on the | 550 | * @write_byte: [REPLACEABLE] write a single byte to the chip on the |
@@ -644,6 +647,8 @@ struct nand_chip { | |||
644 | void __iomem *IO_ADDR_R; | 647 | void __iomem *IO_ADDR_R; |
645 | void __iomem *IO_ADDR_W; | 648 | void __iomem *IO_ADDR_W; |
646 | 649 | ||
650 | struct device_node *dn; | ||
651 | |||
647 | uint8_t (*read_byte)(struct mtd_info *mtd); | 652 | uint8_t (*read_byte)(struct mtd_info *mtd); |
648 | u16 (*read_word)(struct mtd_info *mtd); | 653 | u16 (*read_word)(struct mtd_info *mtd); |
649 | void (*write_byte)(struct mtd_info *mtd, uint8_t byte); | 654 | void (*write_byte)(struct mtd_info *mtd, uint8_t byte); |
@@ -833,7 +838,6 @@ struct nand_manufacturers { | |||
833 | extern struct nand_flash_dev nand_flash_ids[]; | 838 | extern struct nand_flash_dev nand_flash_ids[]; |
834 | extern struct nand_manufacturers nand_manuf_ids[]; | 839 | extern struct nand_manufacturers nand_manuf_ids[]; |
835 | 840 | ||
836 | extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd); | ||
837 | extern int nand_default_bbt(struct mtd_info *mtd); | 841 | extern int nand_default_bbt(struct mtd_info *mtd); |
838 | extern int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs); | 842 | extern int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs); |
839 | extern int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs); | 843 | extern int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs); |