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