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