0001
0002
0003
0004
0005
0006 #ifndef __MTD_MTD_H__
0007 #define __MTD_MTD_H__
0008
0009 #include <linux/types.h>
0010 #include <linux/uio.h>
0011 #include <linux/list.h>
0012 #include <linux/notifier.h>
0013 #include <linux/device.h>
0014 #include <linux/of.h>
0015 #include <linux/nvmem-provider.h>
0016
0017 #include <mtd/mtd-abi.h>
0018
0019 #include <asm/div64.h>
0020
0021 #define MTD_FAIL_ADDR_UNKNOWN -1LL
0022
0023 struct mtd_info;
0024
0025
0026
0027
0028
0029
0030 struct erase_info {
0031 uint64_t addr;
0032 uint64_t len;
0033 uint64_t fail_addr;
0034 };
0035
0036 struct mtd_erase_region_info {
0037 uint64_t offset;
0038 uint32_t erasesize;
0039 uint32_t numblocks;
0040 unsigned long *lockmap;
0041 };
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 struct mtd_oob_ops {
0065 unsigned int mode;
0066 size_t len;
0067 size_t retlen;
0068 size_t ooblen;
0069 size_t oobretlen;
0070 uint32_t ooboffs;
0071 uint8_t *datbuf;
0072 uint8_t *oobbuf;
0073 };
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085 struct mtd_oob_region {
0086 u32 offset;
0087 u32 length;
0088 };
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099 struct mtd_ooblayout_ops {
0100 int (*ecc)(struct mtd_info *mtd, int section,
0101 struct mtd_oob_region *oobecc);
0102 int (*free)(struct mtd_info *mtd, int section,
0103 struct mtd_oob_region *oobfree);
0104 };
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136 struct mtd_pairing_info {
0137 int pair;
0138 int group;
0139 };
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174 struct mtd_pairing_scheme {
0175 int ngroups;
0176 int (*get_info)(struct mtd_info *mtd, int wunit,
0177 struct mtd_pairing_info *info);
0178 int (*get_wunit)(struct mtd_info *mtd,
0179 const struct mtd_pairing_info *info);
0180 };
0181
0182 struct module;
0183
0184
0185
0186
0187
0188
0189 struct mtd_debug_info {
0190 struct dentry *dfs_dir;
0191 };
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206 struct mtd_part {
0207 struct list_head node;
0208 u64 offset;
0209 u64 size;
0210 u32 flags;
0211 };
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225 struct mtd_master {
0226 struct mutex partitions_lock;
0227 struct mutex chrdev_lock;
0228 unsigned int suspended : 1;
0229 };
0230
0231 struct mtd_info {
0232 u_char type;
0233 uint32_t flags;
0234 uint64_t size;
0235
0236
0237
0238
0239
0240 uint32_t erasesize;
0241
0242
0243
0244
0245
0246
0247
0248 uint32_t writesize;
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259 uint32_t writebufsize;
0260
0261 uint32_t oobsize;
0262 uint32_t oobavail;
0263
0264
0265
0266
0267
0268 unsigned int erasesize_shift;
0269 unsigned int writesize_shift;
0270
0271 unsigned int erasesize_mask;
0272 unsigned int writesize_mask;
0273
0274
0275
0276
0277
0278
0279
0280
0281 unsigned int bitflip_threshold;
0282
0283
0284 const char *name;
0285 int index;
0286
0287
0288 const struct mtd_ooblayout_ops *ooblayout;
0289
0290
0291 const struct mtd_pairing_scheme *pairing;
0292
0293
0294 unsigned int ecc_step_size;
0295
0296
0297 unsigned int ecc_strength;
0298
0299
0300
0301
0302 int numeraseregions;
0303 struct mtd_erase_region_info *eraseregions;
0304
0305
0306
0307
0308
0309 int (*_erase) (struct mtd_info *mtd, struct erase_info *instr);
0310 int (*_point) (struct mtd_info *mtd, loff_t from, size_t len,
0311 size_t *retlen, void **virt, resource_size_t *phys);
0312 int (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len);
0313 int (*_read) (struct mtd_info *mtd, loff_t from, size_t len,
0314 size_t *retlen, u_char *buf);
0315 int (*_write) (struct mtd_info *mtd, loff_t to, size_t len,
0316 size_t *retlen, const u_char *buf);
0317 int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len,
0318 size_t *retlen, const u_char *buf);
0319 int (*_read_oob) (struct mtd_info *mtd, loff_t from,
0320 struct mtd_oob_ops *ops);
0321 int (*_write_oob) (struct mtd_info *mtd, loff_t to,
0322 struct mtd_oob_ops *ops);
0323 int (*_get_fact_prot_info) (struct mtd_info *mtd, size_t len,
0324 size_t *retlen, struct otp_info *buf);
0325 int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from,
0326 size_t len, size_t *retlen, u_char *buf);
0327 int (*_get_user_prot_info) (struct mtd_info *mtd, size_t len,
0328 size_t *retlen, struct otp_info *buf);
0329 int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from,
0330 size_t len, size_t *retlen, u_char *buf);
0331 int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to,
0332 size_t len, size_t *retlen,
0333 const u_char *buf);
0334 int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from,
0335 size_t len);
0336 int (*_erase_user_prot_reg) (struct mtd_info *mtd, loff_t from,
0337 size_t len);
0338 int (*_writev) (struct mtd_info *mtd, const struct kvec *vecs,
0339 unsigned long count, loff_t to, size_t *retlen);
0340 void (*_sync) (struct mtd_info *mtd);
0341 int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
0342 int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
0343 int (*_is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
0344 int (*_block_isreserved) (struct mtd_info *mtd, loff_t ofs);
0345 int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs);
0346 int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);
0347 int (*_max_bad_blocks) (struct mtd_info *mtd, loff_t ofs, size_t len);
0348 int (*_suspend) (struct mtd_info *mtd);
0349 void (*_resume) (struct mtd_info *mtd);
0350 void (*_reboot) (struct mtd_info *mtd);
0351
0352
0353
0354
0355 int (*_get_device) (struct mtd_info *mtd);
0356 void (*_put_device) (struct mtd_info *mtd);
0357
0358
0359
0360
0361
0362 bool oops_panic_write;
0363
0364 struct notifier_block reboot_notifier;
0365
0366
0367 struct mtd_ecc_stats ecc_stats;
0368
0369 int subpage_sft;
0370
0371 void *priv;
0372
0373 struct module *owner;
0374 struct device dev;
0375 int usecount;
0376 struct mtd_debug_info dbg;
0377 struct nvmem_device *nvmem;
0378 struct nvmem_device *otp_user_nvmem;
0379 struct nvmem_device *otp_factory_nvmem;
0380
0381
0382
0383
0384
0385
0386
0387 struct mtd_info *parent;
0388
0389
0390 struct list_head partitions;
0391
0392 struct mtd_part part;
0393 struct mtd_master master;
0394 };
0395
0396 static inline struct mtd_info *mtd_get_master(struct mtd_info *mtd)
0397 {
0398 while (mtd->parent)
0399 mtd = mtd->parent;
0400
0401 return mtd;
0402 }
0403
0404 static inline u64 mtd_get_master_ofs(struct mtd_info *mtd, u64 ofs)
0405 {
0406 while (mtd->parent) {
0407 ofs += mtd->part.offset;
0408 mtd = mtd->parent;
0409 }
0410
0411 return ofs;
0412 }
0413
0414 static inline bool mtd_is_partition(const struct mtd_info *mtd)
0415 {
0416 return mtd->parent;
0417 }
0418
0419 static inline bool mtd_has_partitions(const struct mtd_info *mtd)
0420 {
0421 return !list_empty(&mtd->partitions);
0422 }
0423
0424 int mtd_ooblayout_ecc(struct mtd_info *mtd, int section,
0425 struct mtd_oob_region *oobecc);
0426 int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte,
0427 int *section,
0428 struct mtd_oob_region *oobregion);
0429 int mtd_ooblayout_get_eccbytes(struct mtd_info *mtd, u8 *eccbuf,
0430 const u8 *oobbuf, int start, int nbytes);
0431 int mtd_ooblayout_set_eccbytes(struct mtd_info *mtd, const u8 *eccbuf,
0432 u8 *oobbuf, int start, int nbytes);
0433 int mtd_ooblayout_free(struct mtd_info *mtd, int section,
0434 struct mtd_oob_region *oobfree);
0435 int mtd_ooblayout_get_databytes(struct mtd_info *mtd, u8 *databuf,
0436 const u8 *oobbuf, int start, int nbytes);
0437 int mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf,
0438 u8 *oobbuf, int start, int nbytes);
0439 int mtd_ooblayout_count_freebytes(struct mtd_info *mtd);
0440 int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd);
0441
0442 static inline void mtd_set_ooblayout(struct mtd_info *mtd,
0443 const struct mtd_ooblayout_ops *ooblayout)
0444 {
0445 mtd->ooblayout = ooblayout;
0446 }
0447
0448 static inline void mtd_set_pairing_scheme(struct mtd_info *mtd,
0449 const struct mtd_pairing_scheme *pairing)
0450 {
0451 mtd->pairing = pairing;
0452 }
0453
0454 static inline void mtd_set_of_node(struct mtd_info *mtd,
0455 struct device_node *np)
0456 {
0457 mtd->dev.of_node = np;
0458 if (!mtd->name)
0459 of_property_read_string(np, "label", &mtd->name);
0460 }
0461
0462 static inline struct device_node *mtd_get_of_node(struct mtd_info *mtd)
0463 {
0464 return dev_of_node(&mtd->dev);
0465 }
0466
0467 static inline u32 mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
0468 {
0469 return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;
0470 }
0471
0472 static inline int mtd_max_bad_blocks(struct mtd_info *mtd,
0473 loff_t ofs, size_t len)
0474 {
0475 struct mtd_info *master = mtd_get_master(mtd);
0476
0477 if (!master->_max_bad_blocks)
0478 return -ENOTSUPP;
0479
0480 if (mtd->size < (len + ofs) || ofs < 0)
0481 return -EINVAL;
0482
0483 return master->_max_bad_blocks(master, mtd_get_master_ofs(mtd, ofs),
0484 len);
0485 }
0486
0487 int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit,
0488 struct mtd_pairing_info *info);
0489 int mtd_pairing_info_to_wunit(struct mtd_info *mtd,
0490 const struct mtd_pairing_info *info);
0491 int mtd_pairing_groups(struct mtd_info *mtd);
0492 int mtd_erase(struct mtd_info *mtd, struct erase_info *instr);
0493 int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
0494 void **virt, resource_size_t *phys);
0495 int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len);
0496 unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len,
0497 unsigned long offset, unsigned long flags);
0498 int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
0499 u_char *buf);
0500 int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
0501 const u_char *buf);
0502 int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
0503 const u_char *buf);
0504
0505 int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops);
0506 int mtd_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops);
0507
0508 int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
0509 struct otp_info *buf);
0510 int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
0511 size_t *retlen, u_char *buf);
0512 int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
0513 struct otp_info *buf);
0514 int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
0515 size_t *retlen, u_char *buf);
0516 int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len,
0517 size_t *retlen, const u_char *buf);
0518 int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len);
0519 int mtd_erase_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len);
0520
0521 int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
0522 unsigned long count, loff_t to, size_t *retlen);
0523
0524 static inline void mtd_sync(struct mtd_info *mtd)
0525 {
0526 struct mtd_info *master = mtd_get_master(mtd);
0527
0528 if (master->_sync)
0529 master->_sync(master);
0530 }
0531
0532 int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
0533 int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
0534 int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len);
0535 int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs);
0536 int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs);
0537 int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs);
0538
0539 static inline int mtd_suspend(struct mtd_info *mtd)
0540 {
0541 struct mtd_info *master = mtd_get_master(mtd);
0542 int ret;
0543
0544 if (master->master.suspended)
0545 return 0;
0546
0547 ret = master->_suspend ? master->_suspend(master) : 0;
0548 if (ret)
0549 return ret;
0550
0551 master->master.suspended = 1;
0552 return 0;
0553 }
0554
0555 static inline void mtd_resume(struct mtd_info *mtd)
0556 {
0557 struct mtd_info *master = mtd_get_master(mtd);
0558
0559 if (!master->master.suspended)
0560 return;
0561
0562 if (master->_resume)
0563 master->_resume(master);
0564
0565 master->master.suspended = 0;
0566 }
0567
0568 static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd)
0569 {
0570 if (mtd->erasesize_shift)
0571 return sz >> mtd->erasesize_shift;
0572 do_div(sz, mtd->erasesize);
0573 return sz;
0574 }
0575
0576 static inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd)
0577 {
0578 if (mtd->erasesize_shift)
0579 return sz & mtd->erasesize_mask;
0580 return do_div(sz, mtd->erasesize);
0581 }
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592 static inline void mtd_align_erase_req(struct mtd_info *mtd,
0593 struct erase_info *req)
0594 {
0595 u32 mod;
0596
0597 if (WARN_ON(!mtd->erasesize))
0598 return;
0599
0600 mod = mtd_mod_by_eb(req->addr, mtd);
0601 if (mod) {
0602 req->addr -= mod;
0603 req->len += mod;
0604 }
0605
0606 mod = mtd_mod_by_eb(req->addr + req->len, mtd);
0607 if (mod)
0608 req->len += mtd->erasesize - mod;
0609 }
0610
0611 static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd)
0612 {
0613 if (mtd->writesize_shift)
0614 return sz >> mtd->writesize_shift;
0615 do_div(sz, mtd->writesize);
0616 return sz;
0617 }
0618
0619 static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd)
0620 {
0621 if (mtd->writesize_shift)
0622 return sz & mtd->writesize_mask;
0623 return do_div(sz, mtd->writesize);
0624 }
0625
0626 static inline int mtd_wunit_per_eb(struct mtd_info *mtd)
0627 {
0628 struct mtd_info *master = mtd_get_master(mtd);
0629
0630 return master->erasesize / mtd->writesize;
0631 }
0632
0633 static inline int mtd_offset_to_wunit(struct mtd_info *mtd, loff_t offs)
0634 {
0635 return mtd_div_by_ws(mtd_mod_by_eb(offs, mtd), mtd);
0636 }
0637
0638 static inline loff_t mtd_wunit_to_offset(struct mtd_info *mtd, loff_t base,
0639 int wunit)
0640 {
0641 return base + (wunit * mtd->writesize);
0642 }
0643
0644
0645 static inline int mtd_has_oob(const struct mtd_info *mtd)
0646 {
0647 struct mtd_info *master = mtd_get_master((struct mtd_info *)mtd);
0648
0649 return master->_read_oob && master->_write_oob;
0650 }
0651
0652 static inline int mtd_type_is_nand(const struct mtd_info *mtd)
0653 {
0654 return mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH;
0655 }
0656
0657 static inline int mtd_can_have_bb(const struct mtd_info *mtd)
0658 {
0659 struct mtd_info *master = mtd_get_master((struct mtd_info *)mtd);
0660
0661 return !!master->_block_isbad;
0662 }
0663
0664
0665
0666 struct mtd_partition;
0667 struct mtd_part_parser_data;
0668
0669 extern int mtd_device_parse_register(struct mtd_info *mtd,
0670 const char * const *part_probe_types,
0671 struct mtd_part_parser_data *parser_data,
0672 const struct mtd_partition *defparts,
0673 int defnr_parts);
0674 #define mtd_device_register(master, parts, nr_parts) \
0675 mtd_device_parse_register(master, NULL, NULL, parts, nr_parts)
0676 extern int mtd_device_unregister(struct mtd_info *master);
0677 extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
0678 extern int __get_mtd_device(struct mtd_info *mtd);
0679 extern void __put_mtd_device(struct mtd_info *mtd);
0680 extern struct mtd_info *get_mtd_device_nm(const char *name);
0681 extern void put_mtd_device(struct mtd_info *mtd);
0682
0683
0684 struct mtd_notifier {
0685 void (*add)(struct mtd_info *mtd);
0686 void (*remove)(struct mtd_info *mtd);
0687 struct list_head list;
0688 };
0689
0690
0691 extern void register_mtd_user (struct mtd_notifier *new);
0692 extern int unregister_mtd_user (struct mtd_notifier *old);
0693 void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size);
0694
0695 static inline int mtd_is_bitflip(int err) {
0696 return err == -EUCLEAN;
0697 }
0698
0699 static inline int mtd_is_eccerr(int err) {
0700 return err == -EBADMSG;
0701 }
0702
0703 static inline int mtd_is_bitflip_or_eccerr(int err) {
0704 return mtd_is_bitflip(err) || mtd_is_eccerr(err);
0705 }
0706
0707 unsigned mtd_mmap_capabilities(struct mtd_info *mtd);
0708
0709 #ifdef CONFIG_DEBUG_FS
0710 bool mtd_check_expert_analysis_mode(void);
0711 #else
0712 static inline bool mtd_check_expert_analysis_mode(void) { return false; }
0713 #endif
0714
0715
0716 #endif