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