1
2
3
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/notifier.h>
12#include <linux/device.h>
13#include <linux/of.h>
14#include <linux/nvmem-provider.h>
15
16#include <mtd/mtd-abi.h>
17
18#include <asm/div64.h>
19
20#define MTD_FAIL_ADDR_UNKNOWN -1LL
21
22struct mtd_info;
23
24
25
26
27
28
29struct erase_info {
30 uint64_t addr;
31 uint64_t len;
32 uint64_t fail_addr;
33};
34
35struct mtd_erase_region_info {
36 uint64_t offset;
37 uint32_t erasesize;
38 uint32_t numblocks;
39 unsigned long *lockmap;
40};
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63struct mtd_oob_ops {
64 unsigned int mode;
65 size_t len;
66 size_t retlen;
67 size_t ooblen;
68 size_t oobretlen;
69 uint32_t ooboffs;
70 uint8_t *datbuf;
71 uint8_t *oobbuf;
72};
73
74#define MTD_MAX_OOBFREE_ENTRIES_LARGE 32
75#define MTD_MAX_ECCPOS_ENTRIES_LARGE 640
76
77
78
79
80
81
82
83
84
85
86struct mtd_oob_region {
87 u32 offset;
88 u32 length;
89};
90
91
92
93
94
95
96
97
98
99
100struct mtd_ooblayout_ops {
101 int (*ecc)(struct mtd_info *mtd, int section,
102 struct mtd_oob_region *oobecc);
103 int (*free)(struct mtd_info *mtd, int section,
104 struct mtd_oob_region *oobfree);
105};
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137struct mtd_pairing_info {
138 int pair;
139 int group;
140};
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175struct mtd_pairing_scheme {
176 int ngroups;
177 int (*get_info)(struct mtd_info *mtd, int wunit,
178 struct mtd_pairing_info *info);
179 int (*get_wunit)(struct mtd_info *mtd,
180 const struct mtd_pairing_info *info);
181};
182
183struct module;
184
185
186
187
188
189
190struct mtd_debug_info {
191 struct dentry *dfs_dir;
192};
193
194struct mtd_info {
195 u_char type;
196 uint32_t flags;
197 uint32_t orig_flags;
198 uint64_t size;
199
200
201
202
203
204 uint32_t erasesize;
205
206
207
208
209
210
211
212 uint32_t writesize;
213
214
215
216
217
218
219
220
221
222
223 uint32_t writebufsize;
224
225 uint32_t oobsize;
226 uint32_t oobavail;
227
228
229
230
231
232 unsigned int erasesize_shift;
233 unsigned int writesize_shift;
234
235 unsigned int erasesize_mask;
236 unsigned int writesize_mask;
237
238
239
240
241
242
243
244
245 unsigned int bitflip_threshold;
246
247
248 const char *name;
249 int index;
250
251
252 const struct mtd_ooblayout_ops *ooblayout;
253
254
255 const struct mtd_pairing_scheme *pairing;
256
257
258 unsigned int ecc_step_size;
259
260
261 unsigned int ecc_strength;
262
263
264
265
266 int numeraseregions;
267 struct mtd_erase_region_info *eraseregions;
268
269
270
271
272
273 int (*_erase) (struct mtd_info *mtd, struct erase_info *instr);
274 int (*_point) (struct mtd_info *mtd, loff_t from, size_t len,
275 size_t *retlen, void **virt, resource_size_t *phys);
276 int (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len);
277 int (*_read) (struct mtd_info *mtd, loff_t from, size_t len,
278 size_t *retlen, u_char *buf);
279 int (*_write) (struct mtd_info *mtd, loff_t to, size_t len,
280 size_t *retlen, const u_char *buf);
281 int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len,
282 size_t *retlen, const u_char *buf);
283 int (*_read_oob) (struct mtd_info *mtd, loff_t from,
284 struct mtd_oob_ops *ops);
285 int (*_write_oob) (struct mtd_info *mtd, loff_t to,
286 struct mtd_oob_ops *ops);
287 int (*_get_fact_prot_info) (struct mtd_info *mtd, size_t len,
288 size_t *retlen, struct otp_info *buf);
289 int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from,
290 size_t len, size_t *retlen, u_char *buf);
291 int (*_get_user_prot_info) (struct mtd_info *mtd, size_t len,
292 size_t *retlen, struct otp_info *buf);
293 int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from,
294 size_t len, size_t *retlen, u_char *buf);
295 int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to,
296 size_t len, size_t *retlen, u_char *buf);
297 int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from,
298 size_t len);
299 int (*_writev) (struct mtd_info *mtd, const struct kvec *vecs,
300 unsigned long count, loff_t to, size_t *retlen);
301 void (*_sync) (struct mtd_info *mtd);
302 int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
303 int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
304 int (*_is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
305 int (*_block_isreserved) (struct mtd_info *mtd, loff_t ofs);
306 int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs);
307 int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);
308 int (*_max_bad_blocks) (struct mtd_info *mtd, loff_t ofs, size_t len);
309 int (*_suspend) (struct mtd_info *mtd);
310 void (*_resume) (struct mtd_info *mtd);
311 void (*_reboot) (struct mtd_info *mtd);
312
313
314
315
316 int (*_get_device) (struct mtd_info *mtd);
317 void (*_put_device) (struct mtd_info *mtd);
318
319
320
321
322
323 bool oops_panic_write;
324
325 struct notifier_block reboot_notifier;
326
327
328 struct mtd_ecc_stats ecc_stats;
329
330 int subpage_sft;
331
332 void *priv;
333
334 struct module *owner;
335 struct device dev;
336 int usecount;
337 struct mtd_debug_info dbg;
338 struct nvmem_device *nvmem;
339};
340
341int mtd_ooblayout_ecc(struct mtd_info *mtd, int section,
342 struct mtd_oob_region *oobecc);
343int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte,
344 int *section,
345 struct mtd_oob_region *oobregion);
346int mtd_ooblayout_get_eccbytes(struct mtd_info *mtd, u8 *eccbuf,
347 const u8 *oobbuf, int start, int nbytes);
348int mtd_ooblayout_set_eccbytes(struct mtd_info *mtd, const u8 *eccbuf,
349 u8 *oobbuf, int start, int nbytes);
350int mtd_ooblayout_free(struct mtd_info *mtd, int section,
351 struct mtd_oob_region *oobfree);
352int mtd_ooblayout_get_databytes(struct mtd_info *mtd, u8 *databuf,
353 const u8 *oobbuf, int start, int nbytes);
354int mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf,
355 u8 *oobbuf, int start, int nbytes);
356int mtd_ooblayout_count_freebytes(struct mtd_info *mtd);
357int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd);
358
359static inline void mtd_set_ooblayout(struct mtd_info *mtd,
360 const struct mtd_ooblayout_ops *ooblayout)
361{
362 mtd->ooblayout = ooblayout;
363}
364
365static inline void mtd_set_pairing_scheme(struct mtd_info *mtd,
366 const struct mtd_pairing_scheme *pairing)
367{
368 mtd->pairing = pairing;
369}
370
371static inline void mtd_set_of_node(struct mtd_info *mtd,
372 struct device_node *np)
373{
374 mtd->dev.of_node = np;
375 if (!mtd->name)
376 of_property_read_string(np, "label", &mtd->name);
377}
378
379static inline struct device_node *mtd_get_of_node(struct mtd_info *mtd)
380{
381 return dev_of_node(&mtd->dev);
382}
383
384static inline u32 mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
385{
386 return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;
387}
388
389static inline int mtd_max_bad_blocks(struct mtd_info *mtd,
390 loff_t ofs, size_t len)
391{
392 if (!mtd->_max_bad_blocks)
393 return -ENOTSUPP;
394
395 if (mtd->size < (len + ofs) || ofs < 0)
396 return -EINVAL;
397
398 return mtd->_max_bad_blocks(mtd, ofs, len);
399}
400
401int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit,
402 struct mtd_pairing_info *info);
403int mtd_pairing_info_to_wunit(struct mtd_info *mtd,
404 const struct mtd_pairing_info *info);
405int mtd_pairing_groups(struct mtd_info *mtd);
406int mtd_erase(struct mtd_info *mtd, struct erase_info *instr);
407int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
408 void **virt, resource_size_t *phys);
409int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len);
410unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len,
411 unsigned long offset, unsigned long flags);
412int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
413 u_char *buf);
414int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
415 const u_char *buf);
416int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
417 const u_char *buf);
418
419int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops);
420int mtd_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops);
421
422int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
423 struct otp_info *buf);
424int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
425 size_t *retlen, u_char *buf);
426int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
427 struct otp_info *buf);
428int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
429 size_t *retlen, u_char *buf);
430int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len,
431 size_t *retlen, u_char *buf);
432int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len);
433
434int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
435 unsigned long count, loff_t to, size_t *retlen);
436
437static inline void mtd_sync(struct mtd_info *mtd)
438{
439 if (mtd->_sync)
440 mtd->_sync(mtd);
441}
442
443int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
444int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
445int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len);
446int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs);
447int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs);
448int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs);
449
450static inline int mtd_suspend(struct mtd_info *mtd)
451{
452 return mtd->_suspend ? mtd->_suspend(mtd) : 0;
453}
454
455static inline void mtd_resume(struct mtd_info *mtd)
456{
457 if (mtd->_resume)
458 mtd->_resume(mtd);
459}
460
461static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd)
462{
463 if (mtd->erasesize_shift)
464 return sz >> mtd->erasesize_shift;
465 do_div(sz, mtd->erasesize);
466 return sz;
467}
468
469static inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd)
470{
471 if (mtd->erasesize_shift)
472 return sz & mtd->erasesize_mask;
473 return do_div(sz, mtd->erasesize);
474}
475
476
477
478
479
480
481
482
483
484
485static inline void mtd_align_erase_req(struct mtd_info *mtd,
486 struct erase_info *req)
487{
488 u32 mod;
489
490 if (WARN_ON(!mtd->erasesize))
491 return;
492
493 mod = mtd_mod_by_eb(req->addr, mtd);
494 if (mod) {
495 req->addr -= mod;
496 req->len += mod;
497 }
498
499 mod = mtd_mod_by_eb(req->addr + req->len, mtd);
500 if (mod)
501 req->len += mtd->erasesize - mod;
502}
503
504static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd)
505{
506 if (mtd->writesize_shift)
507 return sz >> mtd->writesize_shift;
508 do_div(sz, mtd->writesize);
509 return sz;
510}
511
512static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd)
513{
514 if (mtd->writesize_shift)
515 return sz & mtd->writesize_mask;
516 return do_div(sz, mtd->writesize);
517}
518
519static inline int mtd_wunit_per_eb(struct mtd_info *mtd)
520{
521 return mtd->erasesize / mtd->writesize;
522}
523
524static inline int mtd_offset_to_wunit(struct mtd_info *mtd, loff_t offs)
525{
526 return mtd_div_by_ws(mtd_mod_by_eb(offs, mtd), mtd);
527}
528
529static inline loff_t mtd_wunit_to_offset(struct mtd_info *mtd, loff_t base,
530 int wunit)
531{
532 return base + (wunit * mtd->writesize);
533}
534
535
536static inline int mtd_has_oob(const struct mtd_info *mtd)
537{
538 return mtd->_read_oob && mtd->_write_oob;
539}
540
541static inline int mtd_type_is_nand(const struct mtd_info *mtd)
542{
543 return mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH;
544}
545
546static inline int mtd_can_have_bb(const struct mtd_info *mtd)
547{
548 return !!mtd->_block_isbad;
549}
550
551
552
553struct mtd_partition;
554struct mtd_part_parser_data;
555
556extern int mtd_device_parse_register(struct mtd_info *mtd,
557 const char * const *part_probe_types,
558 struct mtd_part_parser_data *parser_data,
559 const struct mtd_partition *defparts,
560 int defnr_parts);
561#define mtd_device_register(master, parts, nr_parts) \
562 mtd_device_parse_register(master, NULL, NULL, parts, nr_parts)
563extern int mtd_device_unregister(struct mtd_info *master);
564extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
565extern int __get_mtd_device(struct mtd_info *mtd);
566extern void __put_mtd_device(struct mtd_info *mtd);
567extern struct mtd_info *get_mtd_device_nm(const char *name);
568extern void put_mtd_device(struct mtd_info *mtd);
569
570
571struct mtd_notifier {
572 void (*add)(struct mtd_info *mtd);
573 void (*remove)(struct mtd_info *mtd);
574 struct list_head list;
575};
576
577
578extern void register_mtd_user (struct mtd_notifier *new);
579extern int unregister_mtd_user (struct mtd_notifier *old);
580void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size);
581
582static inline int mtd_is_bitflip(int err) {
583 return err == -EUCLEAN;
584}
585
586static inline int mtd_is_eccerr(int err) {
587 return err == -EBADMSG;
588}
589
590static inline int mtd_is_bitflip_or_eccerr(int err) {
591 return mtd_is_bitflip(err) || mtd_is_eccerr(err);
592}
593
594unsigned mtd_mmap_capabilities(struct mtd_info *mtd);
595
596#endif
597