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 struct mutex chrdev_lock;
233 unsigned int suspended : 1;
234};
235
236struct mtd_info {
237 u_char type;
238 uint32_t flags;
239 uint64_t size;
240
241
242
243
244
245 uint32_t erasesize;
246
247
248
249
250
251
252
253 uint32_t writesize;
254
255
256
257
258
259
260
261
262
263
264 uint32_t writebufsize;
265
266 uint32_t oobsize;
267 uint32_t oobavail;
268
269
270
271
272
273 unsigned int erasesize_shift;
274 unsigned int writesize_shift;
275
276 unsigned int erasesize_mask;
277 unsigned int writesize_mask;
278
279
280
281
282
283
284
285
286 unsigned int bitflip_threshold;
287
288
289 const char *name;
290 int index;
291
292
293 const struct mtd_ooblayout_ops *ooblayout;
294
295
296 const struct mtd_pairing_scheme *pairing;
297
298
299 unsigned int ecc_step_size;
300
301
302 unsigned int ecc_strength;
303
304
305
306
307 int numeraseregions;
308 struct mtd_erase_region_info *eraseregions;
309
310
311
312
313
314 int (*_erase) (struct mtd_info *mtd, struct erase_info *instr);
315 int (*_point) (struct mtd_info *mtd, loff_t from, size_t len,
316 size_t *retlen, void **virt, resource_size_t *phys);
317 int (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len);
318 int (*_read) (struct mtd_info *mtd, loff_t from, size_t len,
319 size_t *retlen, u_char *buf);
320 int (*_write) (struct mtd_info *mtd, loff_t to, size_t len,
321 size_t *retlen, const u_char *buf);
322 int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len,
323 size_t *retlen, const u_char *buf);
324 int (*_read_oob) (struct mtd_info *mtd, loff_t from,
325 struct mtd_oob_ops *ops);
326 int (*_write_oob) (struct mtd_info *mtd, loff_t to,
327 struct mtd_oob_ops *ops);
328 int (*_get_fact_prot_info) (struct mtd_info *mtd, size_t len,
329 size_t *retlen, struct otp_info *buf);
330 int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from,
331 size_t len, size_t *retlen, u_char *buf);
332 int (*_get_user_prot_info) (struct mtd_info *mtd, size_t len,
333 size_t *retlen, struct otp_info *buf);
334 int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from,
335 size_t len, size_t *retlen, u_char *buf);
336 int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to,
337 size_t len, size_t *retlen,
338 const u_char *buf);
339 int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from,
340 size_t len);
341 int (*_erase_user_prot_reg) (struct mtd_info *mtd, loff_t from,
342 size_t len);
343 int (*_writev) (struct mtd_info *mtd, const struct kvec *vecs,
344 unsigned long count, loff_t to, size_t *retlen);
345 void (*_sync) (struct mtd_info *mtd);
346 int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
347 int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
348 int (*_is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
349 int (*_block_isreserved) (struct mtd_info *mtd, loff_t ofs);
350 int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs);
351 int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);
352 int (*_max_bad_blocks) (struct mtd_info *mtd, loff_t ofs, size_t len);
353 int (*_suspend) (struct mtd_info *mtd);
354 void (*_resume) (struct mtd_info *mtd);
355 void (*_reboot) (struct mtd_info *mtd);
356
357
358
359
360 int (*_get_device) (struct mtd_info *mtd);
361 void (*_put_device) (struct mtd_info *mtd);
362
363
364
365
366
367 bool oops_panic_write;
368
369 struct notifier_block reboot_notifier;
370
371
372 struct mtd_ecc_stats ecc_stats;
373
374 int subpage_sft;
375
376 void *priv;
377
378 struct module *owner;
379 struct device dev;
380 int usecount;
381 struct mtd_debug_info dbg;
382 struct nvmem_device *nvmem;
383 struct nvmem_device *otp_user_nvmem;
384 struct nvmem_device *otp_factory_nvmem;
385
386
387
388
389
390
391
392 struct mtd_info *parent;
393
394
395 struct list_head partitions;
396
397 union {
398 struct mtd_part part;
399 struct mtd_master master;
400 };
401};
402
403static 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
411static 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
421static inline bool mtd_is_partition(const struct mtd_info *mtd)
422{
423 return mtd->parent;
424}
425
426static inline bool mtd_has_partitions(const struct mtd_info *mtd)
427{
428 return !list_empty(&mtd->partitions);
429}
430
431int mtd_ooblayout_ecc(struct mtd_info *mtd, int section,
432 struct mtd_oob_region *oobecc);
433int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte,
434 int *section,
435 struct mtd_oob_region *oobregion);
436int mtd_ooblayout_get_eccbytes(struct mtd_info *mtd, u8 *eccbuf,
437 const u8 *oobbuf, int start, int nbytes);
438int mtd_ooblayout_set_eccbytes(struct mtd_info *mtd, const u8 *eccbuf,
439 u8 *oobbuf, int start, int nbytes);
440int mtd_ooblayout_free(struct mtd_info *mtd, int section,
441 struct mtd_oob_region *oobfree);
442int mtd_ooblayout_get_databytes(struct mtd_info *mtd, u8 *databuf,
443 const u8 *oobbuf, int start, int nbytes);
444int mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf,
445 u8 *oobbuf, int start, int nbytes);
446int mtd_ooblayout_count_freebytes(struct mtd_info *mtd);
447int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd);
448
449static inline void mtd_set_ooblayout(struct mtd_info *mtd,
450 const struct mtd_ooblayout_ops *ooblayout)
451{
452 mtd->ooblayout = ooblayout;
453}
454
455static inline void mtd_set_pairing_scheme(struct mtd_info *mtd,
456 const struct mtd_pairing_scheme *pairing)
457{
458 mtd->pairing = pairing;
459}
460
461static 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, "label", &mtd->name);
467}
468
469static inline struct device_node *mtd_get_of_node(struct mtd_info *mtd)
470{
471 return dev_of_node(&mtd->dev);
472}
473
474static 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
479static 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
494int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit,
495 struct mtd_pairing_info *info);
496int mtd_pairing_info_to_wunit(struct mtd_info *mtd,
497 const struct mtd_pairing_info *info);
498int mtd_pairing_groups(struct mtd_info *mtd);
499int mtd_erase(struct mtd_info *mtd, struct erase_info *instr);
500int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
501 void **virt, resource_size_t *phys);
502int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len);
503unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len,
504 unsigned long offset, unsigned long flags);
505int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
506 u_char *buf);
507int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
508 const u_char *buf);
509int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
510 const u_char *buf);
511
512int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops);
513int mtd_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops);
514
515int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
516 struct otp_info *buf);
517int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
518 size_t *retlen, u_char *buf);
519int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
520 struct otp_info *buf);
521int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
522 size_t *retlen, u_char *buf);
523int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len,
524 size_t *retlen, const u_char *buf);
525int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len);
526int mtd_erase_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len);
527
528int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
529 unsigned long count, loff_t to, size_t *retlen);
530
531static 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
539int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
540int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
541int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len);
542int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs);
543int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs);
544int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs);
545
546static 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
562static 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
575static 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
583static 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
592
593
594
595
596
597
598
599static 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
618static 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
626static 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
633static 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
640static 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
645static 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
652static inline int mtd_has_oob(const struct mtd_info *mtd)
653{
654 struct mtd_info *master = mtd_get_master((struct mtd_info *)mtd);
655
656 return master->_read_oob && master->_write_oob;
657}
658
659static inline int mtd_type_is_nand(const struct mtd_info *mtd)
660{
661 return mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH;
662}
663
664static inline int mtd_can_have_bb(const struct mtd_info *mtd)
665{
666 struct mtd_info *master = mtd_get_master((struct mtd_info *)mtd);
667
668 return !!master->_block_isbad;
669}
670
671
672
673struct mtd_partition;
674struct mtd_part_parser_data;
675
676extern 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)
683extern int mtd_device_unregister(struct mtd_info *master);
684extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
685extern int __get_mtd_device(struct mtd_info *mtd);
686extern void __put_mtd_device(struct mtd_info *mtd);
687extern struct mtd_info *get_mtd_device_nm(const char *name);
688extern void put_mtd_device(struct mtd_info *mtd);
689
690
691struct mtd_notifier {
692 void (*add)(struct mtd_info *mtd);
693 void (*remove)(struct mtd_info *mtd);
694 struct list_head list;
695};
696
697
698extern void register_mtd_user (struct mtd_notifier *new);
699extern int unregister_mtd_user (struct mtd_notifier *old);
700void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size);
701
702static inline int mtd_is_bitflip(int err) {
703 return err == -EUCLEAN;
704}
705
706static inline int mtd_is_eccerr(int err) {
707 return err == -EBADMSG;
708}
709
710static inline int mtd_is_bitflip_or_eccerr(int err) {
711 return mtd_is_bitflip(err) || mtd_is_eccerr(err);
712}
713
714unsigned mtd_mmap_capabilities(struct mtd_info *mtd);
715
716#endif
717