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/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
23struct mtd_info;
24
25
26
27
28
29
30struct erase_info {
31 uint64_t addr;
32 uint64_t len;
33 uint64_t fail_addr;
34};
35
36struct mtd_erase_region_info {
37 uint64_t offset;
38 uint32_t erasesize;
39 uint32_t numblocks;
40 unsigned long *lockmap;
41};
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64struct mtd_oob_ops {
65 unsigned int mode;
66 size_t len;
67 size_t retlen;
68 size_t ooblen;
69 size_t oobretlen;
70 uint32_t ooboffs;
71 uint8_t *datbuf;
72 uint8_t *oobbuf;
73};
74
75#define MTD_MAX_OOBFREE_ENTRIES_LARGE 32
76#define MTD_MAX_ECCPOS_ENTRIES_LARGE 640
77
78
79
80
81
82
83
84
85
86
87struct mtd_oob_region {
88 u32 offset;
89 u32 length;
90};
91
92
93
94
95
96
97
98
99
100
101struct mtd_ooblayout_ops {
102 int (*ecc)(struct mtd_info *mtd, int section,
103 struct mtd_oob_region *oobecc);
104 int (*free)(struct mtd_info *mtd, int section,
105 struct mtd_oob_region *oobfree);
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
137
138struct mtd_pairing_info {
139 int pair;
140 int group;
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
175
176struct mtd_pairing_scheme {
177 int ngroups;
178 int (*get_info)(struct mtd_info *mtd, int wunit,
179 struct mtd_pairing_info *info);
180 int (*get_wunit)(struct mtd_info *mtd,
181 const struct mtd_pairing_info *info);
182};
183
184struct module;
185
186
187
188
189
190
191struct mtd_debug_info {
192 struct dentry *dfs_dir;
193
194 const char *partname;
195 const char *partid;
196};
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211struct mtd_part {
212 struct list_head node;
213 u64 offset;
214 u64 size;
215 u32 flags;
216};
217
218
219
220
221
222
223
224
225
226
227
228
229
230struct mtd_master {
231 struct mutex partitions_lock;
232 unsigned int suspended : 1;
233};
234
235struct mtd_info {
236 u_char type;
237 uint32_t flags;
238 uint64_t size;
239
240
241
242
243
244 uint32_t erasesize;
245
246
247
248
249
250
251
252 uint32_t writesize;
253
254
255
256
257
258
259
260
261
262
263 uint32_t writebufsize;
264
265 uint32_t oobsize;
266 uint32_t oobavail;
267
268
269
270
271
272 unsigned int erasesize_shift;
273 unsigned int writesize_shift;
274
275 unsigned int erasesize_mask;
276 unsigned int writesize_mask;
277
278
279
280
281
282
283
284
285 unsigned int bitflip_threshold;
286
287
288 const char *name;
289 int index;
290
291
292 const struct mtd_ooblayout_ops *ooblayout;
293
294
295 const struct mtd_pairing_scheme *pairing;
296
297
298 unsigned int ecc_step_size;
299
300
301 unsigned int ecc_strength;
302
303
304
305
306 int numeraseregions;
307 struct mtd_erase_region_info *eraseregions;
308
309
310
311
312
313 int (*_erase) (struct mtd_info *mtd, struct erase_info *instr);
314 int (*_point) (struct mtd_info *mtd, loff_t from, size_t len,
315 size_t *retlen, void **virt, resource_size_t *phys);
316 int (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len);
317 int (*_read) (struct mtd_info *mtd, loff_t from, size_t len,
318 size_t *retlen, u_char *buf);
319 int (*_write) (struct mtd_info *mtd, loff_t to, size_t len,
320 size_t *retlen, const u_char *buf);
321 int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len,
322 size_t *retlen, const u_char *buf);
323 int (*_read_oob) (struct mtd_info *mtd, loff_t from,
324 struct mtd_oob_ops *ops);
325 int (*_write_oob) (struct mtd_info *mtd, loff_t to,
326 struct mtd_oob_ops *ops);
327 int (*_get_fact_prot_info) (struct mtd_info *mtd, size_t len,
328 size_t *retlen, struct otp_info *buf);
329 int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from,
330 size_t len, size_t *retlen, u_char *buf);
331 int (*_get_user_prot_info) (struct mtd_info *mtd, size_t len,
332 size_t *retlen, struct otp_info *buf);
333 int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from,
334 size_t len, size_t *retlen, u_char *buf);
335 int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to,
336 size_t len, size_t *retlen, u_char *buf);
337 int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from,
338 size_t len);
339 int (*_writev) (struct mtd_info *mtd, const struct kvec *vecs,
340 unsigned long count, loff_t to, size_t *retlen);
341 void (*_sync) (struct mtd_info *mtd);
342 int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
343 int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
344 int (*_is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
345 int (*_block_isreserved) (struct mtd_info *mtd, loff_t ofs);
346 int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs);
347 int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);
348 int (*_max_bad_blocks) (struct mtd_info *mtd, loff_t ofs, size_t len);
349 int (*_suspend) (struct mtd_info *mtd);
350 void (*_resume) (struct mtd_info *mtd);
351 void (*_reboot) (struct mtd_info *mtd);
352
353
354
355
356 int (*_get_device) (struct mtd_info *mtd);
357 void (*_put_device) (struct mtd_info *mtd);
358
359
360
361
362
363 bool oops_panic_write;
364
365 struct notifier_block reboot_notifier;
366
367
368 struct mtd_ecc_stats ecc_stats;
369
370 int subpage_sft;
371
372 void *priv;
373
374 struct module *owner;
375 struct device dev;
376 int usecount;
377 struct mtd_debug_info dbg;
378 struct nvmem_device *nvmem;
379
380
381
382
383
384
385
386 struct mtd_info *parent;
387
388
389 struct list_head partitions;
390
391 union {
392 struct mtd_part part;
393 struct mtd_master master;
394 };
395};
396
397static inline struct mtd_info *mtd_get_master(struct mtd_info *mtd)
398{
399 while (mtd->parent)
400 mtd = mtd->parent;
401
402 return mtd;
403}
404
405static inline u64 mtd_get_master_ofs(struct mtd_info *mtd, u64 ofs)
406{
407 while (mtd->parent) {
408 ofs += mtd->part.offset;
409 mtd = mtd->parent;
410 }
411
412 return ofs;
413}
414
415static inline bool mtd_is_partition(const struct mtd_info *mtd)
416{
417 return mtd->parent;
418}
419
420static inline bool mtd_has_partitions(const struct mtd_info *mtd)
421{
422 return !list_empty(&mtd->partitions);
423}
424
425int mtd_ooblayout_ecc(struct mtd_info *mtd, int section,
426 struct mtd_oob_region *oobecc);
427int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte,
428 int *section,
429 struct mtd_oob_region *oobregion);
430int mtd_ooblayout_get_eccbytes(struct mtd_info *mtd, u8 *eccbuf,
431 const u8 *oobbuf, int start, int nbytes);
432int mtd_ooblayout_set_eccbytes(struct mtd_info *mtd, const u8 *eccbuf,
433 u8 *oobbuf, int start, int nbytes);
434int mtd_ooblayout_free(struct mtd_info *mtd, int section,
435 struct mtd_oob_region *oobfree);
436int mtd_ooblayout_get_databytes(struct mtd_info *mtd, u8 *databuf,
437 const u8 *oobbuf, int start, int nbytes);
438int mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf,
439 u8 *oobbuf, int start, int nbytes);
440int mtd_ooblayout_count_freebytes(struct mtd_info *mtd);
441int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd);
442
443static inline void mtd_set_ooblayout(struct mtd_info *mtd,
444 const struct mtd_ooblayout_ops *ooblayout)
445{
446 mtd->ooblayout = ooblayout;
447}
448
449static inline void mtd_set_pairing_scheme(struct mtd_info *mtd,
450 const struct mtd_pairing_scheme *pairing)
451{
452 mtd->pairing = pairing;
453}
454
455static inline void mtd_set_of_node(struct mtd_info *mtd,
456 struct device_node *np)
457{
458 mtd->dev.of_node = np;
459 if (!mtd->name)
460 of_property_read_string(np, "label", &mtd->name);
461}
462
463static inline struct device_node *mtd_get_of_node(struct mtd_info *mtd)
464{
465 return dev_of_node(&mtd->dev);
466}
467
468static inline u32 mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
469{
470 return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;
471}
472
473static inline int mtd_max_bad_blocks(struct mtd_info *mtd,
474 loff_t ofs, size_t len)
475{
476 struct mtd_info *master = mtd_get_master(mtd);
477
478 if (!master->_max_bad_blocks)
479 return -ENOTSUPP;
480
481 if (mtd->size < (len + ofs) || ofs < 0)
482 return -EINVAL;
483
484 return master->_max_bad_blocks(master, mtd_get_master_ofs(mtd, ofs),
485 len);
486}
487
488int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit,
489 struct mtd_pairing_info *info);
490int mtd_pairing_info_to_wunit(struct mtd_info *mtd,
491 const struct mtd_pairing_info *info);
492int mtd_pairing_groups(struct mtd_info *mtd);
493int mtd_erase(struct mtd_info *mtd, struct erase_info *instr);
494int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
495 void **virt, resource_size_t *phys);
496int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len);
497unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len,
498 unsigned long offset, unsigned long flags);
499int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
500 u_char *buf);
501int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
502 const u_char *buf);
503int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
504 const u_char *buf);
505
506int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops);
507int mtd_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops);
508
509int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
510 struct otp_info *buf);
511int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
512 size_t *retlen, u_char *buf);
513int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
514 struct otp_info *buf);
515int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
516 size_t *retlen, u_char *buf);
517int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len,
518 size_t *retlen, u_char *buf);
519int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len);
520
521int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
522 unsigned long count, loff_t to, size_t *retlen);
523
524static inline void mtd_sync(struct mtd_info *mtd)
525{
526 struct mtd_info *master = mtd_get_master(mtd);
527
528 if (master->_sync)
529 master->_sync(master);
530}
531
532int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
533int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
534int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len);
535int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs);
536int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs);
537int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs);
538
539static inline int mtd_suspend(struct mtd_info *mtd)
540{
541 struct mtd_info *master = mtd_get_master(mtd);
542 int ret;
543
544 if (master->master.suspended)
545 return 0;
546
547 ret = master->_suspend ? master->_suspend(master) : 0;
548 if (ret)
549 return ret;
550
551 master->master.suspended = 1;
552 return 0;
553}
554
555static inline void mtd_resume(struct mtd_info *mtd)
556{
557 struct mtd_info *master = mtd_get_master(mtd);
558
559 if (!master->master.suspended)
560 return;
561
562 if (master->_resume)
563 master->_resume(master);
564
565 master->master.suspended = 0;
566}
567
568static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd)
569{
570 if (mtd->erasesize_shift)
571 return sz >> mtd->erasesize_shift;
572 do_div(sz, mtd->erasesize);
573 return sz;
574}
575
576static inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd)
577{
578 if (mtd->erasesize_shift)
579 return sz & mtd->erasesize_mask;
580 return do_div(sz, mtd->erasesize);
581}
582
583
584
585
586
587
588
589
590
591
592static inline void mtd_align_erase_req(struct mtd_info *mtd,
593 struct erase_info *req)
594{
595 u32 mod;
596
597 if (WARN_ON(!mtd->erasesize))
598 return;
599
600 mod = mtd_mod_by_eb(req->addr, mtd);
601 if (mod) {
602 req->addr -= mod;
603 req->len += mod;
604 }
605
606 mod = mtd_mod_by_eb(req->addr + req->len, mtd);
607 if (mod)
608 req->len += mtd->erasesize - mod;
609}
610
611static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd)
612{
613 if (mtd->writesize_shift)
614 return sz >> mtd->writesize_shift;
615 do_div(sz, mtd->writesize);
616 return sz;
617}
618
619static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd)
620{
621 if (mtd->writesize_shift)
622 return sz & mtd->writesize_mask;
623 return do_div(sz, mtd->writesize);
624}
625
626static inline int mtd_wunit_per_eb(struct mtd_info *mtd)
627{
628 struct mtd_info *master = mtd_get_master(mtd);
629
630 return master->erasesize / mtd->writesize;
631}
632
633static inline int mtd_offset_to_wunit(struct mtd_info *mtd, loff_t offs)
634{
635 return mtd_div_by_ws(mtd_mod_by_eb(offs, mtd), mtd);
636}
637
638static inline loff_t mtd_wunit_to_offset(struct mtd_info *mtd, loff_t base,
639 int wunit)
640{
641 return base + (wunit * mtd->writesize);
642}
643
644
645static inline int mtd_has_oob(const struct mtd_info *mtd)
646{
647 struct mtd_info *master = mtd_get_master((struct mtd_info *)mtd);
648
649 return master->_read_oob && master->_write_oob;
650}
651
652static inline int mtd_type_is_nand(const struct mtd_info *mtd)
653{
654 return mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH;
655}
656
657static inline int mtd_can_have_bb(const struct mtd_info *mtd)
658{
659 struct mtd_info *master = mtd_get_master((struct mtd_info *)mtd);
660
661 return !!master->_block_isbad;
662}
663
664
665
666struct mtd_partition;
667struct mtd_part_parser_data;
668
669extern int mtd_device_parse_register(struct mtd_info *mtd,
670 const char * const *part_probe_types,
671 struct mtd_part_parser_data *parser_data,
672 const struct mtd_partition *defparts,
673 int defnr_parts);
674#define mtd_device_register(master, parts, nr_parts) \
675 mtd_device_parse_register(master, NULL, NULL, parts, nr_parts)
676extern int mtd_device_unregister(struct mtd_info *master);
677extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
678extern int __get_mtd_device(struct mtd_info *mtd);
679extern void __put_mtd_device(struct mtd_info *mtd);
680extern struct mtd_info *get_mtd_device_nm(const char *name);
681extern void put_mtd_device(struct mtd_info *mtd);
682
683
684struct mtd_notifier {
685 void (*add)(struct mtd_info *mtd);
686 void (*remove)(struct mtd_info *mtd);
687 struct list_head list;
688};
689
690
691extern void register_mtd_user (struct mtd_notifier *new);
692extern int unregister_mtd_user (struct mtd_notifier *old);
693void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size);
694
695static inline int mtd_is_bitflip(int err) {
696 return err == -EUCLEAN;
697}
698
699static inline int mtd_is_eccerr(int err) {
700 return err == -EBADMSG;
701}
702
703static inline int mtd_is_bitflip_or_eccerr(int err) {
704 return mtd_is_bitflip(err) || mtd_is_eccerr(err);
705}
706
707unsigned mtd_mmap_capabilities(struct mtd_info *mtd);
708
709#endif
710