1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
2 | /* |
3 | * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> et al. |
4 | */ |
5 | |
6 | #ifndef __MTD_MTD_H__ |
7 | #define __MTD_MTD_H__ |
8 | |
9 | #include <linux/types.h> |
10 | #include <linux/uio.h> |
11 | #include <linux/list.h> |
12 | #include <linux/notifier.h> |
13 | #include <linux/device.h> |
14 | #include <linux/of.h> |
15 | #include <linux/nvmem-provider.h> |
16 | |
17 | #include <mtd/mtd-abi.h> |
18 | |
19 | #include <asm/div64.h> |
20 | |
21 | #define MTD_FAIL_ADDR_UNKNOWN -1LL |
22 | |
23 | struct mtd_info; |
24 | |
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 | */ |
30 | struct erase_info { |
31 | uint64_t addr; |
32 | uint64_t len; |
33 | uint64_t fail_addr; |
34 | }; |
35 | |
36 | struct mtd_erase_region_info { |
37 | uint64_t offset; /* At which this region starts, from the beginning of the MTD */ |
38 | uint32_t erasesize; /* For this region */ |
39 | uint32_t numblocks; /* Number of blocks of erasesize in this region */ |
40 | unsigned long *lockmap; /* If keeping bitmap of locks */ |
41 | }; |
42 | |
43 | struct mtd_req_stats { |
44 | unsigned int uncorrectable_errors; |
45 | unsigned int corrected_bitflips; |
46 | unsigned int max_bitflips; |
47 | }; |
48 | |
49 | /** |
50 | * struct mtd_oob_ops - oob operation operands |
51 | * @mode: operation mode |
52 | * |
53 | * @len: number of data bytes to write/read |
54 | * |
55 | * @retlen: number of data bytes written/read |
56 | * |
57 | * @ooblen: number of oob bytes to write/read |
58 | * @oobretlen: number of oob bytes written/read |
59 | * @ooboffs: offset of oob data in the oob area (only relevant when |
60 | * mode = MTD_OPS_PLACE_OOB or MTD_OPS_RAW) |
61 | * @datbuf: data buffer - if NULL only oob data are read/written |
62 | * @oobbuf: oob data buffer |
63 | * |
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. |
69 | */ |
70 | struct mtd_oob_ops { |
71 | unsigned int mode; |
72 | size_t len; |
73 | size_t retlen; |
74 | size_t ooblen; |
75 | size_t oobretlen; |
76 | uint32_t ooboffs; |
77 | uint8_t *datbuf; |
78 | uint8_t *oobbuf; |
79 | struct mtd_req_stats *stats; |
80 | }; |
81 | |
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 | |
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 | |
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 | |
189 | struct module; /* only needed for owner field in mtd_info */ |
190 | |
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 | |
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 |
205 | * @size: partition size. Should be equal to mtd->size unless |
206 | * MTD_SLC_ON_MLC_EMULATION is set |
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; |
216 | u64 size; |
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; |
234 | struct mutex chrdev_lock; |
235 | unsigned int suspended : 1; |
236 | }; |
237 | |
238 | struct mtd_info { |
239 | u_char type; |
240 | uint32_t flags; |
241 | uint64_t size; // Total size of the MTD |
242 | |
243 | /* "Major" erase size for the device. Naïve users may take this |
244 | * to be the only erase size available, or may use the more detailed |
245 | * information below if they desire |
246 | */ |
247 | uint32_t erasesize; |
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. |
254 | */ |
255 | uint32_t writesize; |
256 | |
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 | |
268 | uint32_t oobsize; // Amount of OOB data per block (e.g. 16) |
269 | uint32_t oobavail; // Available OOB bytes per block |
270 | |
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; |
280 | |
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 | |
290 | /* Kernel-only stuff starts here. */ |
291 | const char *name; |
292 | int index; |
293 | |
294 | /* OOB layout description */ |
295 | const struct mtd_ooblayout_ops *ooblayout; |
296 | |
297 | /* NAND pairing scheme, only provided for MLC/TLC NANDs */ |
298 | const struct mtd_pairing_scheme *pairing; |
299 | |
300 | /* the ecc step size. */ |
301 | unsigned int ecc_step_size; |
302 | |
303 | /* max number of correctible bit errors per ecc step */ |
304 | unsigned int ecc_strength; |
305 | |
306 | /* Data for variable erase regions. If numeraseregions is zero, |
307 | * it means that the whole device has erasesize as given above. |
308 | */ |
309 | int numeraseregions; |
310 | struct mtd_erase_region_info *eraseregions; |
311 | |
312 | /* |
313 | * Do not call via these pointers, use corresponding mtd_*() |
314 | * wrappers instead. |
315 | */ |
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); |
319 | int (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len); |
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, |
327 | struct mtd_oob_ops *ops); |
328 | int (*_write_oob) (struct mtd_info *mtd, loff_t to, |
329 | struct mtd_oob_ops *ops); |
330 | int (*_get_fact_prot_info) (struct mtd_info *mtd, size_t len, |
331 | size_t *retlen, struct otp_info *buf); |
332 | int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, |
333 | size_t len, size_t *retlen, u_char *buf); |
334 | int (*_get_user_prot_info) (struct mtd_info *mtd, size_t len, |
335 | size_t *retlen, struct otp_info *buf); |
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, |
339 | size_t len, size_t *retlen, |
340 | const u_char *buf); |
341 | int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, |
342 | size_t len); |
343 | int (*_erase_user_prot_reg) (struct mtd_info *mtd, loff_t from, |
344 | size_t len); |
345 | int (*_writev) (struct mtd_info *mtd, const struct kvec *vecs, |
346 | unsigned long count, loff_t to, size_t *retlen); |
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); |
351 | int (*_block_isreserved) (struct mtd_info *mtd, loff_t ofs); |
352 | int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs); |
353 | int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); |
354 | int (*_max_bad_blocks) (struct mtd_info *mtd, loff_t ofs, size_t len); |
355 | int (*_suspend) (struct mtd_info *mtd); |
356 | void (*_resume) (struct mtd_info *mtd); |
357 | void (*_reboot) (struct mtd_info *mtd); |
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 | */ |
362 | int (*_get_device) (struct mtd_info *mtd); |
363 | void (*_put_device) (struct mtd_info *mtd); |
364 | |
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 | |
371 | struct notifier_block reboot_notifier; /* default mode before reboot */ |
372 | |
373 | /* ECC status information */ |
374 | struct mtd_ecc_stats ecc_stats; |
375 | /* Subpage shift (NAND) */ |
376 | int subpage_sft; |
377 | |
378 | void *priv; |
379 | |
380 | struct module *owner; |
381 | struct device dev; |
382 | struct kref refcnt; |
383 | struct mtd_debug_info dbg; |
384 | struct nvmem_device *nvmem; |
385 | struct nvmem_device *otp_user_nvmem; |
386 | struct nvmem_device *otp_factory_nvmem; |
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 | |
399 | struct mtd_part part; |
400 | struct mtd_master master; |
401 | }; |
402 | |
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(head: &mtd->partitions); |
429 | } |
430 | |
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 | |
449 | static inline void mtd_set_ooblayout(struct mtd_info *mtd, |
450 | const struct mtd_ooblayout_ops *ooblayout) |
451 | { |
452 | mtd->ooblayout = ooblayout; |
453 | } |
454 | |
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 | |
461 | static inline void mtd_set_of_node(struct mtd_info *mtd, |
462 | struct device_node *np) |
463 | { |
464 | mtd->dev.of_node = np; |
465 | if (!mtd->name) |
466 | of_property_read_string(np, propname: "label" , out_string: &mtd->name); |
467 | } |
468 | |
469 | static inline struct device_node *mtd_get_of_node(struct mtd_info *mtd) |
470 | { |
471 | return dev_of_node(dev: &mtd->dev); |
472 | } |
473 | |
474 | static inline u32 mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops) |
475 | { |
476 | return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize; |
477 | } |
478 | |
479 | static inline int mtd_max_bad_blocks(struct mtd_info *mtd, |
480 | loff_t ofs, size_t len) |
481 | { |
482 | struct mtd_info *master = mtd_get_master(mtd); |
483 | |
484 | if (!master->_max_bad_blocks) |
485 | return -ENOTSUPP; |
486 | |
487 | if (mtd->size < (len + ofs) || ofs < 0) |
488 | return -EINVAL; |
489 | |
490 | return master->_max_bad_blocks(master, mtd_get_master_ofs(mtd, ofs), |
491 | len); |
492 | } |
493 | |
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); |
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); |
511 | |
512 | int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); |
513 | int mtd_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops); |
514 | |
515 | int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, |
516 | struct otp_info *buf); |
517 | int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, |
518 | size_t *retlen, u_char *buf); |
519 | int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, |
520 | struct otp_info *buf); |
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, |
524 | size_t *retlen, const u_char *buf); |
525 | int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len); |
526 | int mtd_erase_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len); |
527 | |
528 | int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, |
529 | unsigned long count, loff_t to, size_t *retlen); |
530 | |
531 | static inline void mtd_sync(struct mtd_info *mtd) |
532 | { |
533 | struct mtd_info *master = mtd_get_master(mtd); |
534 | |
535 | if (master->_sync) |
536 | master->_sync(master); |
537 | } |
538 | |
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); |
542 | int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs); |
543 | int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs); |
544 | int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs); |
545 | |
546 | static inline int mtd_suspend(struct mtd_info *mtd) |
547 | { |
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; |
560 | } |
561 | |
562 | static inline void mtd_resume(struct mtd_info *mtd) |
563 | { |
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; |
573 | } |
574 | |
575 | static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd) |
576 | { |
577 | if (mtd->erasesize_shift) |
578 | return sz >> mtd->erasesize_shift; |
579 | do_div(sz, mtd->erasesize); |
580 | return sz; |
581 | } |
582 | |
583 | static inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd) |
584 | { |
585 | if (mtd->erasesize_shift) |
586 | return sz & mtd->erasesize_mask; |
587 | return do_div(sz, mtd->erasesize); |
588 | } |
589 | |
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(sz: req->addr, mtd); |
608 | if (mod) { |
609 | req->addr -= mod; |
610 | req->len += mod; |
611 | } |
612 | |
613 | mod = mtd_mod_by_eb(sz: req->addr + req->len, mtd); |
614 | if (mod) |
615 | req->len += mtd->erasesize - mod; |
616 | } |
617 | |
618 | static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd) |
619 | { |
620 | if (mtd->writesize_shift) |
621 | return sz >> mtd->writesize_shift; |
622 | do_div(sz, mtd->writesize); |
623 | return sz; |
624 | } |
625 | |
626 | static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd) |
627 | { |
628 | if (mtd->writesize_shift) |
629 | return sz & mtd->writesize_mask; |
630 | return do_div(sz, mtd->writesize); |
631 | } |
632 | |
633 | static inline int mtd_wunit_per_eb(struct mtd_info *mtd) |
634 | { |
635 | struct mtd_info *master = mtd_get_master(mtd); |
636 | |
637 | return master->erasesize / mtd->writesize; |
638 | } |
639 | |
640 | static inline int mtd_offset_to_wunit(struct mtd_info *mtd, loff_t offs) |
641 | { |
642 | return mtd_div_by_ws(sz: mtd_mod_by_eb(sz: 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 | |
652 | static inline int mtd_has_oob(const struct mtd_info *mtd) |
653 | { |
654 | struct mtd_info *master = mtd_get_master(mtd: (struct mtd_info *)mtd); |
655 | |
656 | return master->_read_oob && master->_write_oob; |
657 | } |
658 | |
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 | |
664 | static inline int mtd_can_have_bb(const struct mtd_info *mtd) |
665 | { |
666 | struct mtd_info *master = mtd_get_master(mtd: (struct mtd_info *)mtd); |
667 | |
668 | return !!master->_block_isbad; |
669 | } |
670 | |
671 | /* Kernel-side ioctl definitions */ |
672 | |
673 | struct mtd_partition; |
674 | struct mtd_part_parser_data; |
675 | |
676 | extern int mtd_device_parse_register(struct mtd_info *mtd, |
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); |
681 | #define mtd_device_register(master, parts, nr_parts) \ |
682 | mtd_device_parse_register(master, NULL, NULL, parts, nr_parts) |
683 | extern int mtd_device_unregister(struct mtd_info *master); |
684 | extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num); |
685 | extern int __get_mtd_device(struct mtd_info *mtd); |
686 | extern void __put_mtd_device(struct mtd_info *mtd); |
687 | extern struct mtd_info *of_get_mtd_device_by_node(struct device_node *np); |
688 | extern struct mtd_info *get_mtd_device_nm(const char *name); |
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); |
701 | void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size); |
702 | |
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 | } |
714 | |
715 | unsigned mtd_mmap_capabilities(struct mtd_info *mtd); |
716 | |
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 | |
723 | |
724 | #endif /* __MTD_MTD_H__ */ |
725 | |