Commit | Line | Data |
---|---|---|
fd534e9b | 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
61ecfa87 | 2 | /* |
a1452a37 | 3 | * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> et al. |
1da177e4 LT |
4 | */ |
5 | ||
6 | #ifndef __MTD_MTD_H__ | |
7 | #define __MTD_MTD_H__ | |
8 | ||
1da177e4 | 9 | #include <linux/types.h> |
1da177e4 | 10 | #include <linux/uio.h> |
46b5889c | 11 | #include <linux/list.h> |
963a6fb0 | 12 | #include <linux/notifier.h> |
1f24b5a8 | 13 | #include <linux/device.h> |
28309572 | 14 | #include <linux/of.h> |
c4dfa25a | 15 | #include <linux/nvmem-provider.h> |
1da177e4 | 16 | |
1da177e4 LT |
17 | #include <mtd/mtd-abi.h> |
18 | ||
69423d99 AH |
19 | #include <asm/div64.h> |
20 | ||
69423d99 | 21 | #define MTD_FAIL_ADDR_UNKNOWN -1LL |
bb0eb217 | 22 | |
8f347c42 BB |
23 | struct mtd_info; |
24 | ||
e2e24e8e BN |
25 | /* |
26 | * If the erase fails, fail_addr might indicate exactly which block failed. If | |
27 | * fail_addr = MTD_FAIL_ADDR_UNKNOWN, the failure was not at the device level | |
28 | * or was not specific to any particular block. | |
29 | */ | |
1da177e4 | 30 | struct erase_info { |
69423d99 AH |
31 | uint64_t addr; |
32 | uint64_t len; | |
33 | uint64_t fail_addr; | |
1da177e4 LT |
34 | }; |
35 | ||
36 | struct mtd_erase_region_info { | |
e2e24e8e | 37 | uint64_t offset; /* At which this region starts, from the beginning of the MTD */ |
26cdb67c DW |
38 | uint32_t erasesize; /* For this region */ |
39 | uint32_t numblocks; /* Number of blocks of erasesize in this region */ | |
0ecbc81a | 40 | unsigned long *lockmap; /* If keeping bitmap of locks */ |
1da177e4 LT |
41 | }; |
42 | ||
65394169 | 43 | struct mtd_req_stats { |
7bea6056 MK |
44 | unsigned int uncorrectable_errors; |
45 | unsigned int corrected_bitflips; | |
65394169 MK |
46 | unsigned int max_bitflips; |
47 | }; | |
48 | ||
8593fbc6 TG |
49 | /** |
50 | * struct mtd_oob_ops - oob operation operands | |
51 | * @mode: operation mode | |
52 | * | |
7014568b | 53 | * @len: number of data bytes to write/read |
8593fbc6 | 54 | * |
7014568b | 55 | * @retlen: number of data bytes written/read |
8593fbc6 | 56 | * |
7014568b VW |
57 | * @ooblen: number of oob bytes to write/read |
58 | * @oobretlen: number of oob bytes written/read | |
8593fbc6 | 59 | * @ooboffs: offset of oob data in the oob area (only relevant when |
4180f24a | 60 | * mode = MTD_OPS_PLACE_OOB or MTD_OPS_RAW) |
8593fbc6 TG |
61 | * @datbuf: data buffer - if NULL only oob data are read/written |
62 | * @oobbuf: oob data buffer | |
73a4421c | 63 | * |
d70420bc MR |
64 | * Note, some MTD drivers do not allow you to write more than one OOB area at |
65 | * one go. If you try to do that on such an MTD device, -EINVAL will be | |
66 | * returned. If you want to make your implementation portable on all kind of MTD | |
67 | * devices you should split the write request into several sub-requests when the | |
68 | * request crosses a page boundary. | |
8593fbc6 TG |
69 | */ |
70 | struct mtd_oob_ops { | |
905c6bcd | 71 | unsigned int mode; |
8593fbc6 TG |
72 | size_t len; |
73 | size_t retlen; | |
74 | size_t ooblen; | |
7014568b | 75 | size_t oobretlen; |
8593fbc6 TG |
76 | uint32_t ooboffs; |
77 | uint8_t *datbuf; | |
78 | uint8_t *oobbuf; | |
65394169 | 79 | struct mtd_req_stats *stats; |
8593fbc6 TG |
80 | }; |
81 | ||
75eb2cec BB |
82 | /** |
83 | * struct mtd_oob_region - oob region definition | |
84 | * @offset: region offset | |
85 | * @length: region length | |
86 | * | |
87 | * This structure describes a region of the OOB area, and is used | |
88 | * to retrieve ECC or free bytes sections. | |
89 | * Each section is defined by an offset within the OOB area and a | |
90 | * length. | |
91 | */ | |
92 | struct mtd_oob_region { | |
93 | u32 offset; | |
94 | u32 length; | |
95 | }; | |
96 | ||
adbbc3bc BB |
97 | /* |
98 | * struct mtd_ooblayout_ops - NAND OOB layout operations | |
99 | * @ecc: function returning an ECC region in the OOB area. | |
100 | * Should return -ERANGE if %section exceeds the total number of | |
101 | * ECC sections. | |
102 | * @free: function returning a free region in the OOB area. | |
103 | * Should return -ERANGE if %section exceeds the total number of | |
104 | * free sections. | |
105 | */ | |
106 | struct mtd_ooblayout_ops { | |
107 | int (*ecc)(struct mtd_info *mtd, int section, | |
108 | struct mtd_oob_region *oobecc); | |
109 | int (*free)(struct mtd_info *mtd, int section, | |
110 | struct mtd_oob_region *oobfree); | |
111 | }; | |
112 | ||
477b0229 BB |
113 | /** |
114 | * struct mtd_pairing_info - page pairing information | |
115 | * | |
116 | * @pair: pair id | |
117 | * @group: group id | |
118 | * | |
119 | * The term "pair" is used here, even though TLC NANDs might group pages by 3 | |
120 | * (3 bits in a single cell). A pair should regroup all pages that are sharing | |
121 | * the same cell. Pairs are then indexed in ascending order. | |
122 | * | |
123 | * @group is defining the position of a page in a given pair. It can also be | |
124 | * seen as the bit position in the cell: page attached to bit 0 belongs to | |
125 | * group 0, page attached to bit 1 belongs to group 1, etc. | |
126 | * | |
127 | * Example: | |
128 | * The H27UCG8T2BTR-BC datasheet describes the following pairing scheme: | |
129 | * | |
130 | * group-0 group-1 | |
131 | * | |
132 | * pair-0 page-0 page-4 | |
133 | * pair-1 page-1 page-5 | |
134 | * pair-2 page-2 page-8 | |
135 | * ... | |
136 | * pair-127 page-251 page-255 | |
137 | * | |
138 | * | |
139 | * Note that the "group" and "pair" terms were extracted from Samsung and | |
140 | * Hynix datasheets, and might be referenced under other names in other | |
141 | * datasheets (Micron is describing this concept as "shared pages"). | |
142 | */ | |
143 | struct mtd_pairing_info { | |
144 | int pair; | |
145 | int group; | |
146 | }; | |
147 | ||
148 | /** | |
149 | * struct mtd_pairing_scheme - page pairing scheme description | |
150 | * | |
151 | * @ngroups: number of groups. Should be related to the number of bits | |
152 | * per cell. | |
153 | * @get_info: converts a write-unit (page number within an erase block) into | |
154 | * mtd_pairing information (pair + group). This function should | |
155 | * fill the info parameter based on the wunit index or return | |
156 | * -EINVAL if the wunit parameter is invalid. | |
157 | * @get_wunit: converts pairing information into a write-unit (page) number. | |
158 | * This function should return the wunit index pointed by the | |
159 | * pairing information described in the info argument. It should | |
160 | * return -EINVAL, if there's no wunit corresponding to the | |
161 | * passed pairing information. | |
162 | * | |
163 | * See mtd_pairing_info documentation for a detailed explanation of the | |
164 | * pair and group concepts. | |
165 | * | |
166 | * The mtd_pairing_scheme structure provides a generic solution to represent | |
167 | * NAND page pairing scheme. Instead of exposing two big tables to do the | |
168 | * write-unit <-> (pair + group) conversions, we ask the MTD drivers to | |
169 | * implement the ->get_info() and ->get_wunit() functions. | |
170 | * | |
171 | * MTD users will then be able to query these information by using the | |
172 | * mtd_pairing_info_to_wunit() and mtd_wunit_to_pairing_info() helpers. | |
173 | * | |
174 | * @ngroups is here to help MTD users iterating over all the pages in a | |
175 | * given pair. This value can be retrieved by MTD users using the | |
176 | * mtd_pairing_groups() helper. | |
177 | * | |
178 | * Examples are given in the mtd_pairing_info_to_wunit() and | |
179 | * mtd_wunit_to_pairing_info() documentation. | |
180 | */ | |
181 | struct mtd_pairing_scheme { | |
182 | int ngroups; | |
183 | int (*get_info)(struct mtd_info *mtd, int wunit, | |
184 | struct mtd_pairing_info *info); | |
185 | int (*get_wunit)(struct mtd_info *mtd, | |
186 | const struct mtd_pairing_info *info); | |
187 | }; | |
188 | ||
de477254 PG |
189 | struct module; /* only needed for owner field in mtd_info */ |
190 | ||
e8e3edb9 MR |
191 | /** |
192 | * struct mtd_debug_info - debugging information for an MTD device. | |
193 | * | |
194 | * @dfs_dir: direntry object of the MTD device debugfs directory | |
195 | */ | |
196 | struct mtd_debug_info { | |
197 | struct dentry *dfs_dir; | |
198 | }; | |
199 | ||
46b5889c MR |
200 | /** |
201 | * struct mtd_part - MTD partition specific fields | |
202 | * | |
203 | * @node: list node used to add an MTD partition to the parent partition list | |
204 | * @offset: offset of the partition relatively to the parent offset | |
9e3307a1 BB |
205 | * @size: partition size. Should be equal to mtd->size unless |
206 | * MTD_SLC_ON_MLC_EMULATION is set | |
46b5889c MR |
207 | * @flags: original flags (before the mtdpart logic decided to tweak them based |
208 | * on flash constraints, like eraseblock/pagesize alignment) | |
209 | * | |
210 | * This struct is embedded in mtd_info and contains partition-specific | |
211 | * properties/fields. | |
212 | */ | |
213 | struct mtd_part { | |
214 | struct list_head node; | |
215 | u64 offset; | |
9e3307a1 | 216 | u64 size; |
46b5889c MR |
217 | u32 flags; |
218 | }; | |
219 | ||
220 | /** | |
221 | * struct mtd_master - MTD master specific fields | |
222 | * | |
223 | * @partitions_lock: lock protecting accesses to the partition list. Protects | |
224 | * not only the master partition list, but also all | |
225 | * sub-partitions. | |
226 | * @suspended: et to 1 when the device is suspended, 0 otherwise | |
227 | * | |
228 | * This struct is embedded in mtd_info and contains master-specific | |
229 | * properties/fields. The master is the root MTD device from the MTD partition | |
230 | * point of view. | |
231 | */ | |
232 | struct mtd_master { | |
233 | struct mutex partitions_lock; | |
1ad55288 | 234 | struct mutex chrdev_lock; |
46b5889c MR |
235 | unsigned int suspended : 1; |
236 | }; | |
237 | ||
1da177e4 LT |
238 | struct mtd_info { |
239 | u_char type; | |
26cdb67c | 240 | uint32_t flags; |
69423d99 | 241 | uint64_t size; // Total size of the MTD |
1da177e4 | 242 | |
151e7659 | 243 | /* "Major" erase size for the device. Naïve users may take this |
1da177e4 LT |
244 | * to be the only erase size available, or may use the more detailed |
245 | * information below if they desire | |
246 | */ | |
26cdb67c | 247 | uint32_t erasesize; |
783ed81f AB |
248 | /* Minimal writable flash unit size. In case of NOR flash it is 1 (even |
249 | * though individual bits can be cleared), in case of NAND flash it is | |
250 | * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR | |
251 | * it is of ECC block size, etc. It is illegal to have writesize = 0. | |
252 | * Any driver registering a struct mtd_info must ensure a writesize of | |
253 | * 1 or larger. | |
28318776 | 254 | */ |
26cdb67c | 255 | uint32_t writesize; |
1da177e4 | 256 | |
0e4ca7e5 AG |
257 | /* |
258 | * Size of the write buffer used by the MTD. MTD devices having a write | |
259 | * buffer can write multiple writesize chunks at a time. E.g. while | |
260 | * writing 4 * writesize bytes to a device with 2 * writesize bytes | |
261 | * buffer the MTD driver can (but doesn't have to) do 2 writesize | |
262 | * operations, but not 4. Currently, all NANDs have writebufsize | |
263 | * equivalent to writesize (NAND page size). Some NOR flashes do have | |
264 | * writebufsize greater than writesize. | |
265 | */ | |
266 | uint32_t writebufsize; | |
267 | ||
26cdb67c DW |
268 | uint32_t oobsize; // Amount of OOB data per block (e.g. 16) |
269 | uint32_t oobavail; // Available OOB bytes per block | |
1da177e4 | 270 | |
69423d99 AH |
271 | /* |
272 | * If erasesize is a power of 2 then the shift is stored in | |
273 | * erasesize_shift otherwise erasesize_shift is zero. Ditto writesize. | |
274 | */ | |
275 | unsigned int erasesize_shift; | |
276 | unsigned int writesize_shift; | |
277 | /* Masks based on erasesize_shift and writesize_shift */ | |
278 | unsigned int erasesize_mask; | |
279 | unsigned int writesize_mask; | |
638d9838 | 280 | |
d062d4ed MD |
281 | /* |
282 | * read ops return -EUCLEAN if max number of bitflips corrected on any | |
283 | * one region comprising an ecc step equals or exceeds this value. | |
284 | * Settable by driver, else defaults to ecc_strength. User can override | |
285 | * in sysfs. N.B. The meaning of the -EUCLEAN return code has changed; | |
286 | * see Documentation/ABI/testing/sysfs-class-mtd for more detail. | |
287 | */ | |
288 | unsigned int bitflip_threshold; | |
289 | ||
971e4aee | 290 | /* Kernel-only stuff starts here. */ |
eadcf0d7 | 291 | const char *name; |
1da177e4 LT |
292 | int index; |
293 | ||
adbbc3bc BB |
294 | /* OOB layout description */ |
295 | const struct mtd_ooblayout_ops *ooblayout; | |
296 | ||
477b0229 BB |
297 | /* NAND pairing scheme, only provided for MLC/TLC NANDs */ |
298 | const struct mtd_pairing_scheme *pairing; | |
299 | ||
c41a0582 HS |
300 | /* the ecc step size. */ |
301 | unsigned int ecc_step_size; | |
302 | ||
86c2072b | 303 | /* max number of correctible bit errors per ecc step */ |
1d0b95b0 MD |
304 | unsigned int ecc_strength; |
305 | ||
1da177e4 | 306 | /* Data for variable erase regions. If numeraseregions is zero, |
61ecfa87 | 307 | * it means that the whole device has erasesize as given above. |
1da177e4 LT |
308 | */ |
309 | int numeraseregions; | |
61ecfa87 | 310 | struct mtd_erase_region_info *eraseregions; |
1da177e4 | 311 | |
b38178ee | 312 | /* |
7e1f0dc0 AB |
313 | * Do not call via these pointers, use corresponding mtd_*() |
314 | * wrappers instead. | |
b38178ee | 315 | */ |
3c3c10bb AB |
316 | int (*_erase) (struct mtd_info *mtd, struct erase_info *instr); |
317 | int (*_point) (struct mtd_info *mtd, loff_t from, size_t len, | |
318 | size_t *retlen, void **virt, resource_size_t *phys); | |
5e4e6e3f | 319 | int (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len); |
3c3c10bb AB |
320 | int (*_read) (struct mtd_info *mtd, loff_t from, size_t len, |
321 | size_t *retlen, u_char *buf); | |
322 | int (*_write) (struct mtd_info *mtd, loff_t to, size_t len, | |
323 | size_t *retlen, const u_char *buf); | |
324 | int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len, | |
325 | size_t *retlen, const u_char *buf); | |
326 | int (*_read_oob) (struct mtd_info *mtd, loff_t from, | |
a2cc5ba0 | 327 | struct mtd_oob_ops *ops); |
3c3c10bb AB |
328 | int (*_write_oob) (struct mtd_info *mtd, loff_t to, |
329 | struct mtd_oob_ops *ops); | |
4b78fc42 CR |
330 | int (*_get_fact_prot_info) (struct mtd_info *mtd, size_t len, |
331 | size_t *retlen, struct otp_info *buf); | |
3c3c10bb AB |
332 | int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, |
333 | size_t len, size_t *retlen, u_char *buf); | |
4b78fc42 CR |
334 | int (*_get_user_prot_info) (struct mtd_info *mtd, size_t len, |
335 | size_t *retlen, struct otp_info *buf); | |
3c3c10bb AB |
336 | int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from, |
337 | size_t len, size_t *retlen, u_char *buf); | |
338 | int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to, | |
1df1fc8c TA |
339 | size_t len, size_t *retlen, |
340 | const u_char *buf); | |
3c3c10bb AB |
341 | int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, |
342 | size_t len); | |
e3c1f1c9 MW |
343 | int (*_erase_user_prot_reg) (struct mtd_info *mtd, loff_t from, |
344 | size_t len); | |
3c3c10bb | 345 | int (*_writev) (struct mtd_info *mtd, const struct kvec *vecs, |
b0a31f7b | 346 | unsigned long count, loff_t to, size_t *retlen); |
3c3c10bb AB |
347 | void (*_sync) (struct mtd_info *mtd); |
348 | int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); | |
349 | int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); | |
350 | int (*_is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len); | |
8471bb73 | 351 | int (*_block_isreserved) (struct mtd_info *mtd, loff_t ofs); |
3c3c10bb AB |
352 | int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs); |
353 | int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); | |
6080ef6e | 354 | int (*_max_bad_blocks) (struct mtd_info *mtd, loff_t ofs, size_t len); |
3c3c10bb AB |
355 | int (*_suspend) (struct mtd_info *mtd); |
356 | void (*_resume) (struct mtd_info *mtd); | |
3efe41be | 357 | void (*_reboot) (struct mtd_info *mtd); |
a88d2dc6 AB |
358 | /* |
359 | * If the driver is something smart, like UBI, it may need to maintain | |
360 | * its own reference counting. The below functions are only for driver. | |
361 | */ | |
3c3c10bb AB |
362 | int (*_get_device) (struct mtd_info *mtd); |
363 | void (*_put_device) (struct mtd_info *mtd); | |
402d3265 | 364 | |
9f897bfd KD |
365 | /* |
366 | * flag indicates a panic write, low level drivers can take appropriate | |
367 | * action if required to ensure writes go through | |
368 | */ | |
369 | bool oops_panic_write; | |
370 | ||
963a6fb0 NP |
371 | struct notifier_block reboot_notifier; /* default mode before reboot */ |
372 | ||
7fac4648 TG |
373 | /* ECC status information */ |
374 | struct mtd_ecc_stats ecc_stats; | |
29072b96 TG |
375 | /* Subpage shift (NAND) */ |
376 | int subpage_sft; | |
7fac4648 | 377 | |
1da177e4 LT |
378 | void *priv; |
379 | ||
380 | struct module *owner; | |
1f24b5a8 | 381 | struct device dev; |
19bfa9eb | 382 | struct kref refcnt; |
e8e3edb9 | 383 | struct mtd_debug_info dbg; |
c4dfa25a | 384 | struct nvmem_device *nvmem; |
4b361cfa MW |
385 | struct nvmem_device *otp_user_nvmem; |
386 | struct nvmem_device *otp_factory_nvmem; | |
46b5889c MR |
387 | |
388 | /* | |
389 | * Parent device from the MTD partition point of view. | |
390 | * | |
391 | * MTD masters do not have any parent, MTD partitions do. The parent | |
392 | * MTD device can itself be a partition. | |
393 | */ | |
394 | struct mtd_info *parent; | |
395 | ||
396 | /* List of partitions attached to this MTD device */ | |
397 | struct list_head partitions; | |
398 | ||
37c5f9e8 OO |
399 | struct mtd_part part; |
400 | struct mtd_master master; | |
1da177e4 LT |
401 | }; |
402 | ||
46b5889c MR |
403 | static inline struct mtd_info *mtd_get_master(struct mtd_info *mtd) |
404 | { | |
405 | while (mtd->parent) | |
406 | mtd = mtd->parent; | |
407 | ||
408 | return mtd; | |
409 | } | |
410 | ||
411 | static inline u64 mtd_get_master_ofs(struct mtd_info *mtd, u64 ofs) | |
412 | { | |
413 | while (mtd->parent) { | |
414 | ofs += mtd->part.offset; | |
415 | mtd = mtd->parent; | |
416 | } | |
417 | ||
418 | return ofs; | |
419 | } | |
420 | ||
421 | static inline bool mtd_is_partition(const struct mtd_info *mtd) | |
422 | { | |
423 | return mtd->parent; | |
424 | } | |
425 | ||
426 | static inline bool mtd_has_partitions(const struct mtd_info *mtd) | |
427 | { | |
428 | return !list_empty(&mtd->partitions); | |
429 | } | |
430 | ||
75eb2cec BB |
431 | int mtd_ooblayout_ecc(struct mtd_info *mtd, int section, |
432 | struct mtd_oob_region *oobecc); | |
433 | int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte, | |
434 | int *section, | |
435 | struct mtd_oob_region *oobregion); | |
436 | int mtd_ooblayout_get_eccbytes(struct mtd_info *mtd, u8 *eccbuf, | |
437 | const u8 *oobbuf, int start, int nbytes); | |
438 | int mtd_ooblayout_set_eccbytes(struct mtd_info *mtd, const u8 *eccbuf, | |
439 | u8 *oobbuf, int start, int nbytes); | |
440 | int mtd_ooblayout_free(struct mtd_info *mtd, int section, | |
441 | struct mtd_oob_region *oobfree); | |
442 | int mtd_ooblayout_get_databytes(struct mtd_info *mtd, u8 *databuf, | |
443 | const u8 *oobbuf, int start, int nbytes); | |
444 | int mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf, | |
445 | u8 *oobbuf, int start, int nbytes); | |
446 | int mtd_ooblayout_count_freebytes(struct mtd_info *mtd); | |
447 | int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd); | |
448 | ||
adbbc3bc BB |
449 | static inline void mtd_set_ooblayout(struct mtd_info *mtd, |
450 | const struct mtd_ooblayout_ops *ooblayout) | |
036d6543 | 451 | { |
adbbc3bc | 452 | mtd->ooblayout = ooblayout; |
036d6543 BB |
453 | } |
454 | ||
477b0229 BB |
455 | static inline void mtd_set_pairing_scheme(struct mtd_info *mtd, |
456 | const struct mtd_pairing_scheme *pairing) | |
457 | { | |
458 | mtd->pairing = pairing; | |
459 | } | |
460 | ||
28b8b26b BN |
461 | static inline void mtd_set_of_node(struct mtd_info *mtd, |
462 | struct device_node *np) | |
463 | { | |
464 | mtd->dev.of_node = np; | |
28309572 CLG |
465 | if (!mtd->name) |
466 | of_property_read_string(np, "label", &mtd->name); | |
28b8b26b BN |
467 | } |
468 | ||
469 | static inline struct device_node *mtd_get_of_node(struct mtd_info *mtd) | |
470 | { | |
4a67c9fd | 471 | return dev_of_node(&mtd->dev); |
28b8b26b BN |
472 | } |
473 | ||
4348433d | 474 | static inline u32 mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops) |
29f1058a BB |
475 | { |
476 | return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize; | |
477 | } | |
478 | ||
6080ef6e JW |
479 | static inline int mtd_max_bad_blocks(struct mtd_info *mtd, |
480 | loff_t ofs, size_t len) | |
481 | { | |
46b5889c MR |
482 | struct mtd_info *master = mtd_get_master(mtd); |
483 | ||
484 | if (!master->_max_bad_blocks) | |
6080ef6e JW |
485 | return -ENOTSUPP; |
486 | ||
487 | if (mtd->size < (len + ofs) || ofs < 0) | |
488 | return -EINVAL; | |
489 | ||
46b5889c MR |
490 | return master->_max_bad_blocks(master, mtd_get_master_ofs(mtd, ofs), |
491 | len); | |
6080ef6e JW |
492 | } |
493 | ||
477b0229 BB |
494 | int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit, |
495 | struct mtd_pairing_info *info); | |
496 | int mtd_pairing_info_to_wunit(struct mtd_info *mtd, | |
497 | const struct mtd_pairing_info *info); | |
498 | int mtd_pairing_groups(struct mtd_info *mtd); | |
8273a0c9 AB |
499 | int mtd_erase(struct mtd_info *mtd, struct erase_info *instr); |
500 | int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, | |
501 | void **virt, resource_size_t *phys); | |
502 | int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len); | |
503 | unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len, | |
504 | unsigned long offset, unsigned long flags); | |
505 | int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, | |
506 | u_char *buf); | |
507 | int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, | |
508 | const u_char *buf); | |
509 | int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, | |
510 | const u_char *buf); | |
7ae79d7f | 511 | |
d2d48480 | 512 | int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); |
0c034fe3 | 513 | int mtd_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops); |
a2cc5ba0 | 514 | |
4b78fc42 CR |
515 | int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, |
516 | struct otp_info *buf); | |
de3cac93 AB |
517 | int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, |
518 | size_t *retlen, u_char *buf); | |
4b78fc42 CR |
519 | int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, |
520 | struct otp_info *buf); | |
de3cac93 AB |
521 | int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, |
522 | size_t *retlen, u_char *buf); | |
523 | int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, | |
1df1fc8c | 524 | size_t *retlen, const u_char *buf); |
de3cac93 | 525 | int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len); |
e3c1f1c9 | 526 | int mtd_erase_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len); |
4403dbfb | 527 | |
1dbebd32 AB |
528 | int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, |
529 | unsigned long count, loff_t to, size_t *retlen); | |
b0a31f7b | 530 | |
85f2f2a8 AB |
531 | static inline void mtd_sync(struct mtd_info *mtd) |
532 | { | |
46b5889c MR |
533 | struct mtd_info *master = mtd_get_master(mtd); |
534 | ||
535 | if (master->_sync) | |
536 | master->_sync(master); | |
85f2f2a8 AB |
537 | } |
538 | ||
8273a0c9 AB |
539 | int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); |
540 | int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); | |
541 | int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len); | |
8471bb73 | 542 | int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs); |
8273a0c9 AB |
543 | int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs); |
544 | int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs); | |
e95e9786 | 545 | |
3fe4bae8 AB |
546 | static inline int mtd_suspend(struct mtd_info *mtd) |
547 | { | |
46b5889c MR |
548 | struct mtd_info *master = mtd_get_master(mtd); |
549 | int ret; | |
550 | ||
551 | if (master->master.suspended) | |
552 | return 0; | |
553 | ||
554 | ret = master->_suspend ? master->_suspend(master) : 0; | |
555 | if (ret) | |
556 | return ret; | |
557 | ||
558 | master->master.suspended = 1; | |
559 | return 0; | |
3fe4bae8 AB |
560 | } |
561 | ||
ead995f8 AB |
562 | static inline void mtd_resume(struct mtd_info *mtd) |
563 | { | |
46b5889c MR |
564 | struct mtd_info *master = mtd_get_master(mtd); |
565 | ||
566 | if (!master->master.suspended) | |
567 | return; | |
568 | ||
569 | if (master->_resume) | |
570 | master->_resume(master); | |
571 | ||
572 | master->master.suspended = 0; | |
ead995f8 AB |
573 | } |
574 | ||
26cdb67c | 575 | static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd) |
69423d99 AH |
576 | { |
577 | if (mtd->erasesize_shift) | |
578 | return sz >> mtd->erasesize_shift; | |
579 | do_div(sz, mtd->erasesize); | |
580 | return sz; | |
581 | } | |
582 | ||
26cdb67c | 583 | static inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd) |
69423d99 AH |
584 | { |
585 | if (mtd->erasesize_shift) | |
586 | return sz & mtd->erasesize_mask; | |
587 | return do_div(sz, mtd->erasesize); | |
588 | } | |
589 | ||
f72071b8 BB |
590 | /** |
591 | * mtd_align_erase_req - Adjust an erase request to align things on eraseblock | |
592 | * boundaries. | |
593 | * @mtd: the MTD device this erase request applies on | |
594 | * @req: the erase request to adjust | |
595 | * | |
596 | * This function will adjust @req->addr and @req->len to align them on | |
597 | * @mtd->erasesize. Of course we expect @mtd->erasesize to be != 0. | |
598 | */ | |
599 | static inline void mtd_align_erase_req(struct mtd_info *mtd, | |
600 | struct erase_info *req) | |
601 | { | |
602 | u32 mod; | |
603 | ||
604 | if (WARN_ON(!mtd->erasesize)) | |
605 | return; | |
606 | ||
607 | mod = mtd_mod_by_eb(req->addr, mtd); | |
608 | if (mod) { | |
609 | req->addr -= mod; | |
610 | req->len += mod; | |
611 | } | |
612 | ||
613 | mod = mtd_mod_by_eb(req->addr + req->len, mtd); | |
614 | if (mod) | |
615 | req->len += mtd->erasesize - mod; | |
616 | } | |
617 | ||
26cdb67c | 618 | static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd) |
69423d99 AH |
619 | { |
620 | if (mtd->writesize_shift) | |
621 | return sz >> mtd->writesize_shift; | |
622 | do_div(sz, mtd->writesize); | |
623 | return sz; | |
624 | } | |
625 | ||
26cdb67c | 626 | static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd) |
69423d99 AH |
627 | { |
628 | if (mtd->writesize_shift) | |
629 | return sz & mtd->writesize_mask; | |
630 | return do_div(sz, mtd->writesize); | |
631 | } | |
1da177e4 | 632 | |
477b0229 BB |
633 | static inline int mtd_wunit_per_eb(struct mtd_info *mtd) |
634 | { | |
9e3307a1 BB |
635 | struct mtd_info *master = mtd_get_master(mtd); |
636 | ||
637 | return master->erasesize / mtd->writesize; | |
477b0229 BB |
638 | } |
639 | ||
640 | static inline int mtd_offset_to_wunit(struct mtd_info *mtd, loff_t offs) | |
641 | { | |
642 | return mtd_div_by_ws(mtd_mod_by_eb(offs, mtd), mtd); | |
643 | } | |
644 | ||
645 | static inline loff_t mtd_wunit_to_offset(struct mtd_info *mtd, loff_t base, | |
646 | int wunit) | |
647 | { | |
648 | return base + (wunit * mtd->writesize); | |
649 | } | |
650 | ||
651 | ||
fc002e3c AB |
652 | static inline int mtd_has_oob(const struct mtd_info *mtd) |
653 | { | |
46b5889c MR |
654 | struct mtd_info *master = mtd_get_master((struct mtd_info *)mtd); |
655 | ||
656 | return master->_read_oob && master->_write_oob; | |
fc002e3c AB |
657 | } |
658 | ||
818b9739 HS |
659 | static inline int mtd_type_is_nand(const struct mtd_info *mtd) |
660 | { | |
661 | return mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH; | |
662 | } | |
663 | ||
8f461a73 AB |
664 | static inline int mtd_can_have_bb(const struct mtd_info *mtd) |
665 | { | |
46b5889c MR |
666 | struct mtd_info *master = mtd_get_master((struct mtd_info *)mtd); |
667 | ||
668 | return !!master->_block_isbad; | |
8f461a73 AB |
669 | } |
670 | ||
1da177e4 LT |
671 | /* Kernel-side ioctl definitions */ |
672 | ||
f5671ab3 | 673 | struct mtd_partition; |
c7975330 | 674 | struct mtd_part_parser_data; |
f5671ab3 | 675 | |
1c4c215c | 676 | extern int mtd_device_parse_register(struct mtd_info *mtd, |
26a47346 AB |
677 | const char * const *part_probe_types, |
678 | struct mtd_part_parser_data *parser_data, | |
679 | const struct mtd_partition *defparts, | |
680 | int defnr_parts); | |
15c60a50 DES |
681 | #define mtd_device_register(master, parts, nr_parts) \ |
682 | mtd_device_parse_register(master, NULL, NULL, parts, nr_parts) | |
f5671ab3 | 683 | extern int mtd_device_unregister(struct mtd_info *master); |
1da177e4 | 684 | extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num); |
3bd45657 ML |
685 | extern int __get_mtd_device(struct mtd_info *mtd); |
686 | extern void __put_mtd_device(struct mtd_info *mtd); | |
4a575865 | 687 | extern struct mtd_info *of_get_mtd_device_by_node(struct device_node *np); |
7799308f | 688 | extern struct mtd_info *get_mtd_device_nm(const char *name); |
1da177e4 LT |
689 | extern void put_mtd_device(struct mtd_info *mtd); |
690 | ||
691 | ||
692 | struct mtd_notifier { | |
693 | void (*add)(struct mtd_info *mtd); | |
694 | void (*remove)(struct mtd_info *mtd); | |
695 | struct list_head list; | |
696 | }; | |
697 | ||
698 | ||
699 | extern void register_mtd_user (struct mtd_notifier *new); | |
700 | extern int unregister_mtd_user (struct mtd_notifier *old); | |
33b53716 GE |
701 | void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size); |
702 | ||
7387ce77 BN |
703 | static inline int mtd_is_bitflip(int err) { |
704 | return err == -EUCLEAN; | |
705 | } | |
706 | ||
707 | static inline int mtd_is_eccerr(int err) { | |
708 | return err == -EBADMSG; | |
709 | } | |
710 | ||
711 | static inline int mtd_is_bitflip_or_eccerr(int err) { | |
712 | return mtd_is_bitflip(err) || mtd_is_eccerr(err); | |
713 | } | |
1da177e4 | 714 | |
b4caecd4 CH |
715 | unsigned mtd_mmap_capabilities(struct mtd_info *mtd); |
716 | ||
ad5e35f5 MR |
717 | #ifdef CONFIG_DEBUG_FS |
718 | bool mtd_check_expert_analysis_mode(void); | |
719 | #else | |
720 | static inline bool mtd_check_expert_analysis_mode(void) { return false; } | |
721 | #endif | |
722 | ||
67b967dd | 723 | |
1da177e4 | 724 | #endif /* __MTD_MTD_H__ */ |