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