1932394acSWolfgang Denk /* 2932394acSWolfgang Denk * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al. 3932394acSWolfgang Denk * 4932394acSWolfgang Denk * Released under GPL 5932394acSWolfgang Denk */ 6932394acSWolfgang Denk 7932394acSWolfgang Denk #ifndef __MTD_MTD_H__ 8932394acSWolfgang Denk #define __MTD_MTD_H__ 9cfa460adSWilliam Juul 10932394acSWolfgang Denk #include <linux/types.h> 118d2effeaSStefan Roese #include <div64.h> 12*dfe64e2cSSergey Lapin #include <mtd/mtd-abi.h> 13*dfe64e2cSSergey Lapin #include <asm/errno.h> 14932394acSWolfgang Denk 15cfa460adSWilliam Juul #define MTD_CHAR_MAJOR 90 16cfa460adSWilliam Juul #define MTD_BLOCK_MAJOR 31 17cfa460adSWilliam Juul #define MAX_MTD_DEVICES 32 18932394acSWolfgang Denk 19932394acSWolfgang Denk #define MTD_ERASE_PENDING 0x01 20932394acSWolfgang Denk #define MTD_ERASING 0x02 21932394acSWolfgang Denk #define MTD_ERASE_SUSPEND 0x04 22932394acSWolfgang Denk #define MTD_ERASE_DONE 0x08 23932394acSWolfgang Denk #define MTD_ERASE_FAILED 0x10 24932394acSWolfgang Denk 258d2effeaSStefan Roese #define MTD_FAIL_ADDR_UNKNOWN -1LL 268d2effeaSStefan Roese 27d438d508SKyungmin Park /* 28d438d508SKyungmin Park * Enumeration for NAND/OneNAND flash chip state 29d438d508SKyungmin Park */ 30d438d508SKyungmin Park enum { 31d438d508SKyungmin Park FL_READY, 32d438d508SKyungmin Park FL_READING, 33d438d508SKyungmin Park FL_WRITING, 34d438d508SKyungmin Park FL_ERASING, 35d438d508SKyungmin Park FL_SYNCING, 36d438d508SKyungmin Park FL_CACHEDPRG, 37d438d508SKyungmin Park FL_RESETING, 38d438d508SKyungmin Park FL_UNLOCKING, 39d438d508SKyungmin Park FL_LOCKING, 40d438d508SKyungmin Park FL_PM_SUSPENDED, 41d438d508SKyungmin Park }; 42d438d508SKyungmin Park 43932394acSWolfgang Denk /* If the erase fails, fail_addr might indicate exactly which block failed. If 448d2effeaSStefan Roese fail_addr = MTD_FAIL_ADDR_UNKNOWN, the failure was not at the device level or was not 45932394acSWolfgang Denk specific to any particular block. */ 46932394acSWolfgang Denk struct erase_info { 47932394acSWolfgang Denk struct mtd_info *mtd; 488d2effeaSStefan Roese uint64_t addr; 498d2effeaSStefan Roese uint64_t len; 508d2effeaSStefan Roese uint64_t fail_addr; 51932394acSWolfgang Denk u_long time; 52932394acSWolfgang Denk u_long retries; 53932394acSWolfgang Denk u_int dev; 54932394acSWolfgang Denk u_int cell; 55932394acSWolfgang Denk void (*callback) (struct erase_info *self); 56932394acSWolfgang Denk u_long priv; 57932394acSWolfgang Denk u_char state; 58932394acSWolfgang Denk struct erase_info *next; 596d41419fSMarek Vasut int scrub; 60932394acSWolfgang Denk }; 61932394acSWolfgang Denk 62932394acSWolfgang Denk struct mtd_erase_region_info { 638d2effeaSStefan Roese uint64_t offset; /* At which this region starts, from the beginning of the MTD */ 64932394acSWolfgang Denk u_int32_t erasesize; /* For this region */ 65932394acSWolfgang Denk u_int32_t numblocks; /* Number of blocks of erasesize in this region */ 66cfa460adSWilliam Juul unsigned long *lockmap; /* If keeping bitmap of locks */ 67cfa460adSWilliam Juul }; 68cfa460adSWilliam Juul 69cfa460adSWilliam Juul /** 70cfa460adSWilliam Juul * struct mtd_oob_ops - oob operation operands 71cfa460adSWilliam Juul * @mode: operation mode 72cfa460adSWilliam Juul * 73cfa460adSWilliam Juul * @len: number of data bytes to write/read 74cfa460adSWilliam Juul * 75cfa460adSWilliam Juul * @retlen: number of data bytes written/read 76cfa460adSWilliam Juul * 77cfa460adSWilliam Juul * @ooblen: number of oob bytes to write/read 78cfa460adSWilliam Juul * @oobretlen: number of oob bytes written/read 79cfa460adSWilliam Juul * @ooboffs: offset of oob data in the oob area (only relevant when 80*dfe64e2cSSergey Lapin * mode = MTD_OPS_PLACE_OOB or MTD_OPS_RAW) 81cfa460adSWilliam Juul * @datbuf: data buffer - if NULL only oob data are read/written 82cfa460adSWilliam Juul * @oobbuf: oob data buffer 83cfa460adSWilliam Juul * 84cfa460adSWilliam Juul * Note, it is allowed to read more then one OOB area at one go, but not write. 85cfa460adSWilliam Juul * The interface assumes that the OOB write requests program only one page's 86cfa460adSWilliam Juul * OOB area. 87cfa460adSWilliam Juul */ 88cfa460adSWilliam Juul struct mtd_oob_ops { 89*dfe64e2cSSergey Lapin unsigned int mode; 90cfa460adSWilliam Juul size_t len; 91cfa460adSWilliam Juul size_t retlen; 92cfa460adSWilliam Juul size_t ooblen; 93cfa460adSWilliam Juul size_t oobretlen; 94cfa460adSWilliam Juul uint32_t ooboffs; 95cfa460adSWilliam Juul uint8_t *datbuf; 96cfa460adSWilliam Juul uint8_t *oobbuf; 97932394acSWolfgang Denk }; 98932394acSWolfgang Denk 99932394acSWolfgang Denk struct mtd_info { 100932394acSWolfgang Denk u_char type; 101932394acSWolfgang Denk u_int32_t flags; 1028e5e9b94SWolfgang Denk uint64_t size; /* Total size of the MTD */ 103932394acSWolfgang Denk 104fa82f871SAlbert ARIBAUD /* "Major" erase size for the device. Naïve users may take this 105932394acSWolfgang Denk * to be the only erase size available, or may use the more detailed 106932394acSWolfgang Denk * information below if they desire 107932394acSWolfgang Denk */ 108932394acSWolfgang Denk u_int32_t erasesize; 109cfa460adSWilliam Juul /* Minimal writable flash unit size. In case of NOR flash it is 1 (even 110cfa460adSWilliam Juul * though individual bits can be cleared), in case of NAND flash it is 111cfa460adSWilliam Juul * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR 112cfa460adSWilliam Juul * it is of ECC block size, etc. It is illegal to have writesize = 0. 113cfa460adSWilliam Juul * Any driver registering a struct mtd_info must ensure a writesize of 114cfa460adSWilliam Juul * 1 or larger. 115cfa460adSWilliam Juul */ 116cfa460adSWilliam Juul u_int32_t writesize; 117932394acSWolfgang Denk 1184b070809SWolfgang Denk u_int32_t oobsize; /* Amount of OOB data per block (e.g. 16) */ 1194b070809SWolfgang Denk u_int32_t oobavail; /* Available OOB bytes per block */ 120932394acSWolfgang Denk 121*dfe64e2cSSergey Lapin /* 122*dfe64e2cSSergey Lapin * read ops return -EUCLEAN if max number of bitflips corrected on any 123*dfe64e2cSSergey Lapin * one region comprising an ecc step equals or exceeds this value. 124*dfe64e2cSSergey Lapin * Settable by driver, else defaults to ecc_strength. User can override 125*dfe64e2cSSergey Lapin * in sysfs. N.B. The meaning of the -EUCLEAN return code has changed; 126*dfe64e2cSSergey Lapin * see Documentation/ABI/testing/sysfs-class-mtd for more detail. 127*dfe64e2cSSergey Lapin */ 128*dfe64e2cSSergey Lapin unsigned int bitflip_threshold; 129*dfe64e2cSSergey Lapin 1304b070809SWolfgang Denk /* Kernel-only stuff starts here. */ 131c45912d8SScott Wood const char *name; 132932394acSWolfgang Denk int index; 133932394acSWolfgang Denk 134*dfe64e2cSSergey Lapin /* ECC layout structure pointer - read only! */ 135cfa460adSWilliam Juul struct nand_ecclayout *ecclayout; 136932394acSWolfgang Denk 137*dfe64e2cSSergey Lapin /* max number of correctible bit errors per ecc step */ 138*dfe64e2cSSergey Lapin unsigned int ecc_strength; 139*dfe64e2cSSergey Lapin 140932394acSWolfgang Denk /* Data for variable erase regions. If numeraseregions is zero, 141932394acSWolfgang Denk * it means that the whole device has erasesize as given above. 142932394acSWolfgang Denk */ 143932394acSWolfgang Denk int numeraseregions; 144932394acSWolfgang Denk struct mtd_erase_region_info *eraseregions; 145932394acSWolfgang Denk 146c45912d8SScott Wood /* 147*dfe64e2cSSergey Lapin * Do not call via these pointers, use corresponding mtd_*() 148*dfe64e2cSSergey Lapin * wrappers instead. 149c45912d8SScott Wood */ 150*dfe64e2cSSergey Lapin int (*_erase) (struct mtd_info *mtd, struct erase_info *instr); 151*dfe64e2cSSergey Lapin int (*_point) (struct mtd_info *mtd, loff_t from, size_t len, 152c45912d8SScott Wood size_t *retlen, void **virt, phys_addr_t *phys); 153*dfe64e2cSSergey Lapin void (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len); 154*dfe64e2cSSergey Lapin int (*_read) (struct mtd_info *mtd, loff_t from, size_t len, 155*dfe64e2cSSergey Lapin size_t *retlen, u_char *buf); 156*dfe64e2cSSergey Lapin int (*_write) (struct mtd_info *mtd, loff_t to, size_t len, 157*dfe64e2cSSergey Lapin size_t *retlen, const u_char *buf); 158932394acSWolfgang Denk 159c45912d8SScott Wood /* In blackbox flight recorder like scenarios we want to make successful 160c45912d8SScott Wood writes in interrupt context. panic_write() is only intended to be 161c45912d8SScott Wood called when its known the kernel is about to panic and we need the 162c45912d8SScott Wood write to succeed. Since the kernel is not going to be running for much 163c45912d8SScott Wood longer, this function can break locks and delay to ensure the write 164c45912d8SScott Wood succeeds (but not sleep). */ 165c45912d8SScott Wood 166*dfe64e2cSSergey Lapin int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); 167c45912d8SScott Wood 168*dfe64e2cSSergey Lapin int (*_read_oob) (struct mtd_info *mtd, loff_t from, 169cfa460adSWilliam Juul struct mtd_oob_ops *ops); 170*dfe64e2cSSergey Lapin int (*_write_oob) (struct mtd_info *mtd, loff_t to, 171cfa460adSWilliam Juul struct mtd_oob_ops *ops); 172*dfe64e2cSSergey Lapin int (*_get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, 173*dfe64e2cSSergey Lapin size_t len); 174*dfe64e2cSSergey Lapin int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, 175*dfe64e2cSSergey Lapin size_t len, size_t *retlen, u_char *buf); 176*dfe64e2cSSergey Lapin int (*_get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, 177*dfe64e2cSSergey Lapin size_t len); 178*dfe64e2cSSergey Lapin int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from, 179*dfe64e2cSSergey Lapin size_t len, size_t *retlen, u_char *buf); 180*dfe64e2cSSergey Lapin int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to, size_t len, 181*dfe64e2cSSergey Lapin size_t *retlen, u_char *buf); 182*dfe64e2cSSergey Lapin int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, 183*dfe64e2cSSergey Lapin size_t len); 184*dfe64e2cSSergey Lapin void (*_sync) (struct mtd_info *mtd); 185*dfe64e2cSSergey Lapin int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); 186*dfe64e2cSSergey Lapin int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); 187*dfe64e2cSSergey Lapin int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs); 188*dfe64e2cSSergey Lapin int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); 189932394acSWolfgang Denk /* 190*dfe64e2cSSergey Lapin * If the driver is something smart, like UBI, it may need to maintain 191*dfe64e2cSSergey Lapin * its own reference counting. The below functions are only for driver. 192932394acSWolfgang Denk */ 193*dfe64e2cSSergey Lapin int (*_get_device) (struct mtd_info *mtd); 194*dfe64e2cSSergey Lapin void (*_put_device) (struct mtd_info *mtd); 195cfa460adSWilliam Juul 196cfa460adSWilliam Juul /* XXX U-BOOT XXX */ 197932394acSWolfgang Denk #if 0 198cfa460adSWilliam Juul /* kvec-based read/write methods. 199932394acSWolfgang Denk NB: The 'count' parameter is the number of _vectors_, each of 200932394acSWolfgang Denk which contains an (ofs, len) tuple. 201932394acSWolfgang Denk */ 202932394acSWolfgang Denk int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); 203932394acSWolfgang Denk #endif 204cfa460adSWilliam Juul /* XXX U-BOOT XXX */ 205cfa460adSWilliam Juul #if 0 206cfa460adSWilliam Juul struct notifier_block reboot_notifier; /* default mode before reboot */ 207cfa460adSWilliam Juul #endif 208cfa460adSWilliam Juul 209cfa460adSWilliam Juul /* ECC status information */ 210cfa460adSWilliam Juul struct mtd_ecc_stats ecc_stats; 211cfa460adSWilliam Juul /* Subpage shift (NAND) */ 212cfa460adSWilliam Juul int subpage_sft; 213cfa460adSWilliam Juul 214932394acSWolfgang Denk void *priv; 215932394acSWolfgang Denk 216932394acSWolfgang Denk struct module *owner; 217932394acSWolfgang Denk int usecount; 218932394acSWolfgang Denk }; 219932394acSWolfgang Denk 220*dfe64e2cSSergey Lapin int mtd_erase(struct mtd_info *mtd, struct erase_info *instr); 221*dfe64e2cSSergey Lapin int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, 222*dfe64e2cSSergey Lapin u_char *buf); 223*dfe64e2cSSergey Lapin int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, 224*dfe64e2cSSergey Lapin const u_char *buf); 225*dfe64e2cSSergey Lapin int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, 226*dfe64e2cSSergey Lapin const u_char *buf); 227*dfe64e2cSSergey Lapin 228*dfe64e2cSSergey Lapin int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); 229*dfe64e2cSSergey Lapin 230*dfe64e2cSSergey Lapin static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to, 231*dfe64e2cSSergey Lapin struct mtd_oob_ops *ops) 232*dfe64e2cSSergey Lapin { 233*dfe64e2cSSergey Lapin ops->retlen = ops->oobretlen = 0; 234*dfe64e2cSSergey Lapin if (!mtd->_write_oob) 235*dfe64e2cSSergey Lapin return -EOPNOTSUPP; 236*dfe64e2cSSergey Lapin if (!(mtd->flags & MTD_WRITEABLE)) 237*dfe64e2cSSergey Lapin return -EROFS; 238*dfe64e2cSSergey Lapin return mtd->_write_oob(mtd, to, ops); 239*dfe64e2cSSergey Lapin } 240*dfe64e2cSSergey Lapin 241*dfe64e2cSSergey Lapin int mtd_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf, 242*dfe64e2cSSergey Lapin size_t len); 243*dfe64e2cSSergey Lapin int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, 244*dfe64e2cSSergey Lapin size_t *retlen, u_char *buf); 245*dfe64e2cSSergey Lapin int mtd_get_user_prot_info(struct mtd_info *mtd, struct otp_info *buf, 246*dfe64e2cSSergey Lapin size_t len); 247*dfe64e2cSSergey Lapin int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, 248*dfe64e2cSSergey Lapin size_t *retlen, u_char *buf); 249*dfe64e2cSSergey Lapin int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, 250*dfe64e2cSSergey Lapin size_t *retlen, u_char *buf); 251*dfe64e2cSSergey Lapin int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len); 252*dfe64e2cSSergey Lapin 253*dfe64e2cSSergey Lapin /* XXX U-BOOT XXX */ 254*dfe64e2cSSergey Lapin #if 0 255*dfe64e2cSSergey Lapin int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, 256*dfe64e2cSSergey Lapin unsigned long count, loff_t to, size_t *retlen); 257*dfe64e2cSSergey Lapin #endif 258*dfe64e2cSSergey Lapin 259*dfe64e2cSSergey Lapin static inline void mtd_sync(struct mtd_info *mtd) 260*dfe64e2cSSergey Lapin { 261*dfe64e2cSSergey Lapin if (mtd->_sync) 262*dfe64e2cSSergey Lapin mtd->_sync(mtd); 263*dfe64e2cSSergey Lapin } 264*dfe64e2cSSergey Lapin 265*dfe64e2cSSergey Lapin int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); 266*dfe64e2cSSergey Lapin int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); 267*dfe64e2cSSergey Lapin int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len); 268*dfe64e2cSSergey Lapin int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs); 269*dfe64e2cSSergey Lapin int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs); 270*dfe64e2cSSergey Lapin 2718d2effeaSStefan Roese static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd) 2728d2effeaSStefan Roese { 2738d2effeaSStefan Roese do_div(sz, mtd->erasesize); 2748d2effeaSStefan Roese return sz; 2758d2effeaSStefan Roese } 2768d2effeaSStefan Roese 2778d2effeaSStefan Roese static inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd) 2788d2effeaSStefan Roese { 2798d2effeaSStefan Roese return do_div(sz, mtd->erasesize); 2808d2effeaSStefan Roese } 281932394acSWolfgang Denk 282*dfe64e2cSSergey Lapin static inline int mtd_has_oob(const struct mtd_info *mtd) 283*dfe64e2cSSergey Lapin { 284*dfe64e2cSSergey Lapin return mtd->_read_oob && mtd->_write_oob; 285*dfe64e2cSSergey Lapin } 286*dfe64e2cSSergey Lapin 287*dfe64e2cSSergey Lapin static inline int mtd_can_have_bb(const struct mtd_info *mtd) 288*dfe64e2cSSergey Lapin { 289*dfe64e2cSSergey Lapin return !!mtd->_block_isbad; 290*dfe64e2cSSergey Lapin } 291*dfe64e2cSSergey Lapin 292932394acSWolfgang Denk /* Kernel-side ioctl definitions */ 293932394acSWolfgang Denk 294932394acSWolfgang Denk extern int add_mtd_device(struct mtd_info *mtd); 295932394acSWolfgang Denk extern int del_mtd_device (struct mtd_info *mtd); 296932394acSWolfgang Denk 297932394acSWolfgang Denk extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num); 298cfa460adSWilliam Juul extern struct mtd_info *get_mtd_device_nm(const char *name); 299932394acSWolfgang Denk 300932394acSWolfgang Denk extern void put_mtd_device(struct mtd_info *mtd); 3014ba692fbSBen Gardiner extern void mtd_get_len_incl_bad(struct mtd_info *mtd, uint64_t offset, 3024ba692fbSBen Gardiner const uint64_t length, uint64_t *len_incl_bad, 3034ba692fbSBen Gardiner int *truncated); 304cfa460adSWilliam Juul /* XXX U-BOOT XXX */ 305932394acSWolfgang Denk #if 0 306932394acSWolfgang Denk struct mtd_notifier { 307932394acSWolfgang Denk void (*add)(struct mtd_info *mtd); 308932394acSWolfgang Denk void (*remove)(struct mtd_info *mtd); 309932394acSWolfgang Denk struct list_head list; 310932394acSWolfgang Denk }; 311932394acSWolfgang Denk 312932394acSWolfgang Denk extern void register_mtd_user (struct mtd_notifier *new); 313932394acSWolfgang Denk extern int unregister_mtd_user (struct mtd_notifier *old); 314932394acSWolfgang Denk #endif 315932394acSWolfgang Denk 316932394acSWolfgang Denk #ifdef CONFIG_MTD_PARTITIONS 317932394acSWolfgang Denk void mtd_erase_callback(struct erase_info *instr); 318932394acSWolfgang Denk #else 319932394acSWolfgang Denk static inline void mtd_erase_callback(struct erase_info *instr) 320932394acSWolfgang Denk { 321932394acSWolfgang Denk if (instr->callback) 322932394acSWolfgang Denk instr->callback(instr); 323932394acSWolfgang Denk } 324932394acSWolfgang Denk #endif 325932394acSWolfgang Denk 326932394acSWolfgang Denk /* 327932394acSWolfgang Denk * Debugging macro and defines 328932394acSWolfgang Denk */ 329932394acSWolfgang Denk #define MTD_DEBUG_LEVEL0 (0) /* Quiet */ 330932394acSWolfgang Denk #define MTD_DEBUG_LEVEL1 (1) /* Audible */ 331932394acSWolfgang Denk #define MTD_DEBUG_LEVEL2 (2) /* Loud */ 332932394acSWolfgang Denk #define MTD_DEBUG_LEVEL3 (3) /* Noisy */ 333932394acSWolfgang Denk 334932394acSWolfgang Denk #ifdef CONFIG_MTD_DEBUG 335*dfe64e2cSSergey Lapin #define pr_debug(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args) 3363167c538SScott Wood #define MTDDEBUG(n, args...) \ 337932394acSWolfgang Denk do { \ 338932394acSWolfgang Denk if (n <= CONFIG_MTD_DEBUG_VERBOSE) \ 339932394acSWolfgang Denk printk(KERN_INFO args); \ 340932394acSWolfgang Denk } while(0) 341932394acSWolfgang Denk #else /* CONFIG_MTD_DEBUG */ 342*dfe64e2cSSergey Lapin #define pr_debug(args...) 343c45912d8SScott Wood #define MTDDEBUG(n, args...) \ 344c45912d8SScott Wood do { \ 345c45912d8SScott Wood if (0) \ 346c45912d8SScott Wood printk(KERN_INFO args); \ 347c45912d8SScott Wood } while(0) 348932394acSWolfgang Denk #endif /* CONFIG_MTD_DEBUG */ 349*dfe64e2cSSergey Lapin #define pr_info(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args) 350*dfe64e2cSSergey Lapin #define pr_warn(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args) 351*dfe64e2cSSergey Lapin #define pr_err(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args) 352*dfe64e2cSSergey Lapin 353*dfe64e2cSSergey Lapin static inline int mtd_is_bitflip(int err) { 354*dfe64e2cSSergey Lapin return err == -EUCLEAN; 355*dfe64e2cSSergey Lapin } 356*dfe64e2cSSergey Lapin 357*dfe64e2cSSergey Lapin static inline int mtd_is_eccerr(int err) { 358*dfe64e2cSSergey Lapin return err == -EBADMSG; 359*dfe64e2cSSergey Lapin } 360*dfe64e2cSSergey Lapin 361*dfe64e2cSSergey Lapin static inline int mtd_is_bitflip_or_eccerr(int err) { 362*dfe64e2cSSergey Lapin return mtd_is_bitflip(err) || mtd_is_eccerr(err); 363*dfe64e2cSSergey Lapin } 364932394acSWolfgang Denk 365932394acSWolfgang Denk #endif /* __MTD_MTD_H__ */ 366