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> 12dfe64e2cSSergey Lapin #include <mtd/mtd-abi.h> 13dfe64e2cSSergey 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 80dfe64e2cSSergey 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 { 89dfe64e2cSSergey 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 99*68ec9c85SPrabhakar Kushwaha #ifdef CONFIG_SYS_NAND_MAX_OOBFREE 100*68ec9c85SPrabhakar Kushwaha #define MTD_MAX_OOBFREE_ENTRIES_LARGE CONFIG_SYS_NAND_MAX_OOBFREE 101*68ec9c85SPrabhakar Kushwaha #else 102*68ec9c85SPrabhakar Kushwaha #define MTD_MAX_OOBFREE_ENTRIES_LARGE 32 103*68ec9c85SPrabhakar Kushwaha #endif 104*68ec9c85SPrabhakar Kushwaha 105*68ec9c85SPrabhakar Kushwaha #ifdef CONFIG_SYS_NAND_MAX_ECCPOS 106*68ec9c85SPrabhakar Kushwaha #define MTD_MAX_ECCPOS_ENTRIES_LARGE CONFIG_SYS_NAND_MAX_ECCPOS 107*68ec9c85SPrabhakar Kushwaha #else 108*68ec9c85SPrabhakar Kushwaha #define MTD_MAX_ECCPOS_ENTRIES_LARGE 640 109*68ec9c85SPrabhakar Kushwaha #endif 110*68ec9c85SPrabhakar Kushwaha 111*68ec9c85SPrabhakar Kushwaha /* 112*68ec9c85SPrabhakar Kushwaha * ECC layout control structure. Exported to userspace for 113*68ec9c85SPrabhakar Kushwaha * diagnosis and to allow creation of raw images 114*68ec9c85SPrabhakar Kushwaha */ 115*68ec9c85SPrabhakar Kushwaha struct nand_ecclayout { 116*68ec9c85SPrabhakar Kushwaha uint32_t eccbytes; 117*68ec9c85SPrabhakar Kushwaha uint32_t eccpos[MTD_MAX_ECCPOS_ENTRIES_LARGE]; 118*68ec9c85SPrabhakar Kushwaha uint32_t oobavail; 119*68ec9c85SPrabhakar Kushwaha struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE]; 120*68ec9c85SPrabhakar Kushwaha }; 121*68ec9c85SPrabhakar Kushwaha 122932394acSWolfgang Denk struct mtd_info { 123932394acSWolfgang Denk u_char type; 124932394acSWolfgang Denk u_int32_t flags; 1258e5e9b94SWolfgang Denk uint64_t size; /* Total size of the MTD */ 126932394acSWolfgang Denk 127fa82f871SAlbert ARIBAUD /* "Major" erase size for the device. Naïve users may take this 128932394acSWolfgang Denk * to be the only erase size available, or may use the more detailed 129932394acSWolfgang Denk * information below if they desire 130932394acSWolfgang Denk */ 131932394acSWolfgang Denk u_int32_t erasesize; 132cfa460adSWilliam Juul /* Minimal writable flash unit size. In case of NOR flash it is 1 (even 133cfa460adSWilliam Juul * though individual bits can be cleared), in case of NAND flash it is 134cfa460adSWilliam Juul * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR 135cfa460adSWilliam Juul * it is of ECC block size, etc. It is illegal to have writesize = 0. 136cfa460adSWilliam Juul * Any driver registering a struct mtd_info must ensure a writesize of 137cfa460adSWilliam Juul * 1 or larger. 138cfa460adSWilliam Juul */ 139cfa460adSWilliam Juul u_int32_t writesize; 140932394acSWolfgang Denk 1414b070809SWolfgang Denk u_int32_t oobsize; /* Amount of OOB data per block (e.g. 16) */ 1424b070809SWolfgang Denk u_int32_t oobavail; /* Available OOB bytes per block */ 143932394acSWolfgang Denk 144dfe64e2cSSergey Lapin /* 145dfe64e2cSSergey Lapin * read ops return -EUCLEAN if max number of bitflips corrected on any 146dfe64e2cSSergey Lapin * one region comprising an ecc step equals or exceeds this value. 147dfe64e2cSSergey Lapin * Settable by driver, else defaults to ecc_strength. User can override 148dfe64e2cSSergey Lapin * in sysfs. N.B. The meaning of the -EUCLEAN return code has changed; 149dfe64e2cSSergey Lapin * see Documentation/ABI/testing/sysfs-class-mtd for more detail. 150dfe64e2cSSergey Lapin */ 151dfe64e2cSSergey Lapin unsigned int bitflip_threshold; 152dfe64e2cSSergey Lapin 1534b070809SWolfgang Denk /* Kernel-only stuff starts here. */ 154c45912d8SScott Wood const char *name; 155932394acSWolfgang Denk int index; 156932394acSWolfgang Denk 157dfe64e2cSSergey Lapin /* ECC layout structure pointer - read only! */ 158cfa460adSWilliam Juul struct nand_ecclayout *ecclayout; 159932394acSWolfgang Denk 160dfe64e2cSSergey Lapin /* max number of correctible bit errors per ecc step */ 161dfe64e2cSSergey Lapin unsigned int ecc_strength; 162dfe64e2cSSergey Lapin 163932394acSWolfgang Denk /* Data for variable erase regions. If numeraseregions is zero, 164932394acSWolfgang Denk * it means that the whole device has erasesize as given above. 165932394acSWolfgang Denk */ 166932394acSWolfgang Denk int numeraseregions; 167932394acSWolfgang Denk struct mtd_erase_region_info *eraseregions; 168932394acSWolfgang Denk 169c45912d8SScott Wood /* 170dfe64e2cSSergey Lapin * Do not call via these pointers, use corresponding mtd_*() 171dfe64e2cSSergey Lapin * wrappers instead. 172c45912d8SScott Wood */ 173dfe64e2cSSergey Lapin int (*_erase) (struct mtd_info *mtd, struct erase_info *instr); 174dfe64e2cSSergey Lapin int (*_point) (struct mtd_info *mtd, loff_t from, size_t len, 175c45912d8SScott Wood size_t *retlen, void **virt, phys_addr_t *phys); 176dfe64e2cSSergey Lapin void (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len); 177dfe64e2cSSergey Lapin int (*_read) (struct mtd_info *mtd, loff_t from, size_t len, 178dfe64e2cSSergey Lapin size_t *retlen, u_char *buf); 179dfe64e2cSSergey Lapin int (*_write) (struct mtd_info *mtd, loff_t to, size_t len, 180dfe64e2cSSergey Lapin size_t *retlen, const u_char *buf); 181932394acSWolfgang Denk 182c45912d8SScott Wood /* In blackbox flight recorder like scenarios we want to make successful 183c45912d8SScott Wood writes in interrupt context. panic_write() is only intended to be 184c45912d8SScott Wood called when its known the kernel is about to panic and we need the 185c45912d8SScott Wood write to succeed. Since the kernel is not going to be running for much 186c45912d8SScott Wood longer, this function can break locks and delay to ensure the write 187c45912d8SScott Wood succeeds (but not sleep). */ 188c45912d8SScott Wood 189dfe64e2cSSergey Lapin int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); 190c45912d8SScott Wood 191dfe64e2cSSergey Lapin int (*_read_oob) (struct mtd_info *mtd, loff_t from, 192cfa460adSWilliam Juul struct mtd_oob_ops *ops); 193dfe64e2cSSergey Lapin int (*_write_oob) (struct mtd_info *mtd, loff_t to, 194cfa460adSWilliam Juul struct mtd_oob_ops *ops); 195dfe64e2cSSergey Lapin int (*_get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, 196dfe64e2cSSergey Lapin size_t len); 197dfe64e2cSSergey Lapin int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, 198dfe64e2cSSergey Lapin size_t len, size_t *retlen, u_char *buf); 199dfe64e2cSSergey Lapin int (*_get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, 200dfe64e2cSSergey Lapin size_t len); 201dfe64e2cSSergey Lapin int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from, 202dfe64e2cSSergey Lapin size_t len, size_t *retlen, u_char *buf); 203dfe64e2cSSergey Lapin int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to, size_t len, 204dfe64e2cSSergey Lapin size_t *retlen, u_char *buf); 205dfe64e2cSSergey Lapin int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, 206dfe64e2cSSergey Lapin size_t len); 207dfe64e2cSSergey Lapin void (*_sync) (struct mtd_info *mtd); 208dfe64e2cSSergey Lapin int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); 209dfe64e2cSSergey Lapin int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); 210dfe64e2cSSergey Lapin int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs); 211dfe64e2cSSergey Lapin int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); 212932394acSWolfgang Denk /* 213dfe64e2cSSergey Lapin * If the driver is something smart, like UBI, it may need to maintain 214dfe64e2cSSergey Lapin * its own reference counting. The below functions are only for driver. 215932394acSWolfgang Denk */ 216dfe64e2cSSergey Lapin int (*_get_device) (struct mtd_info *mtd); 217dfe64e2cSSergey Lapin void (*_put_device) (struct mtd_info *mtd); 218cfa460adSWilliam Juul 219cfa460adSWilliam Juul /* XXX U-BOOT XXX */ 220932394acSWolfgang Denk #if 0 221cfa460adSWilliam Juul /* kvec-based read/write methods. 222932394acSWolfgang Denk NB: The 'count' parameter is the number of _vectors_, each of 223932394acSWolfgang Denk which contains an (ofs, len) tuple. 224932394acSWolfgang Denk */ 225932394acSWolfgang Denk int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); 226932394acSWolfgang Denk #endif 227cfa460adSWilliam Juul /* XXX U-BOOT XXX */ 228cfa460adSWilliam Juul #if 0 229cfa460adSWilliam Juul struct notifier_block reboot_notifier; /* default mode before reboot */ 230cfa460adSWilliam Juul #endif 231cfa460adSWilliam Juul 232cfa460adSWilliam Juul /* ECC status information */ 233cfa460adSWilliam Juul struct mtd_ecc_stats ecc_stats; 234cfa460adSWilliam Juul /* Subpage shift (NAND) */ 235cfa460adSWilliam Juul int subpage_sft; 236cfa460adSWilliam Juul 237932394acSWolfgang Denk void *priv; 238932394acSWolfgang Denk 239932394acSWolfgang Denk struct module *owner; 240932394acSWolfgang Denk int usecount; 241932394acSWolfgang Denk }; 242932394acSWolfgang Denk 243dfe64e2cSSergey Lapin int mtd_erase(struct mtd_info *mtd, struct erase_info *instr); 244dfe64e2cSSergey Lapin int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, 245dfe64e2cSSergey Lapin u_char *buf); 246dfe64e2cSSergey Lapin int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, 247dfe64e2cSSergey Lapin const u_char *buf); 248dfe64e2cSSergey Lapin int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, 249dfe64e2cSSergey Lapin const u_char *buf); 250dfe64e2cSSergey Lapin 251dfe64e2cSSergey Lapin int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); 252dfe64e2cSSergey Lapin 253dfe64e2cSSergey Lapin static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to, 254dfe64e2cSSergey Lapin struct mtd_oob_ops *ops) 255dfe64e2cSSergey Lapin { 256dfe64e2cSSergey Lapin ops->retlen = ops->oobretlen = 0; 257dfe64e2cSSergey Lapin if (!mtd->_write_oob) 258dfe64e2cSSergey Lapin return -EOPNOTSUPP; 259dfe64e2cSSergey Lapin if (!(mtd->flags & MTD_WRITEABLE)) 260dfe64e2cSSergey Lapin return -EROFS; 261dfe64e2cSSergey Lapin return mtd->_write_oob(mtd, to, ops); 262dfe64e2cSSergey Lapin } 263dfe64e2cSSergey Lapin 264dfe64e2cSSergey Lapin int mtd_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf, 265dfe64e2cSSergey Lapin size_t len); 266dfe64e2cSSergey Lapin int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, 267dfe64e2cSSergey Lapin size_t *retlen, u_char *buf); 268dfe64e2cSSergey Lapin int mtd_get_user_prot_info(struct mtd_info *mtd, struct otp_info *buf, 269dfe64e2cSSergey Lapin size_t len); 270dfe64e2cSSergey Lapin int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, 271dfe64e2cSSergey Lapin size_t *retlen, u_char *buf); 272dfe64e2cSSergey Lapin int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, 273dfe64e2cSSergey Lapin size_t *retlen, u_char *buf); 274dfe64e2cSSergey Lapin int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len); 275dfe64e2cSSergey Lapin 276dfe64e2cSSergey Lapin /* XXX U-BOOT XXX */ 277dfe64e2cSSergey Lapin #if 0 278dfe64e2cSSergey Lapin int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, 279dfe64e2cSSergey Lapin unsigned long count, loff_t to, size_t *retlen); 280dfe64e2cSSergey Lapin #endif 281dfe64e2cSSergey Lapin 282dfe64e2cSSergey Lapin static inline void mtd_sync(struct mtd_info *mtd) 283dfe64e2cSSergey Lapin { 284dfe64e2cSSergey Lapin if (mtd->_sync) 285dfe64e2cSSergey Lapin mtd->_sync(mtd); 286dfe64e2cSSergey Lapin } 287dfe64e2cSSergey Lapin 288dfe64e2cSSergey Lapin int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); 289dfe64e2cSSergey Lapin int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); 290dfe64e2cSSergey Lapin int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len); 291dfe64e2cSSergey Lapin int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs); 292dfe64e2cSSergey Lapin int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs); 293dfe64e2cSSergey Lapin 2948d2effeaSStefan Roese static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd) 2958d2effeaSStefan Roese { 2968d2effeaSStefan Roese do_div(sz, mtd->erasesize); 2978d2effeaSStefan Roese return sz; 2988d2effeaSStefan Roese } 2998d2effeaSStefan Roese 3008d2effeaSStefan Roese static inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd) 3018d2effeaSStefan Roese { 3028d2effeaSStefan Roese return do_div(sz, mtd->erasesize); 3038d2effeaSStefan Roese } 304932394acSWolfgang Denk 305dfe64e2cSSergey Lapin static inline int mtd_has_oob(const struct mtd_info *mtd) 306dfe64e2cSSergey Lapin { 307dfe64e2cSSergey Lapin return mtd->_read_oob && mtd->_write_oob; 308dfe64e2cSSergey Lapin } 309dfe64e2cSSergey Lapin 310dfe64e2cSSergey Lapin static inline int mtd_can_have_bb(const struct mtd_info *mtd) 311dfe64e2cSSergey Lapin { 312dfe64e2cSSergey Lapin return !!mtd->_block_isbad; 313dfe64e2cSSergey Lapin } 314dfe64e2cSSergey Lapin 315932394acSWolfgang Denk /* Kernel-side ioctl definitions */ 316932394acSWolfgang Denk 317932394acSWolfgang Denk extern int add_mtd_device(struct mtd_info *mtd); 318932394acSWolfgang Denk extern int del_mtd_device (struct mtd_info *mtd); 319932394acSWolfgang Denk 320932394acSWolfgang Denk extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num); 321cfa460adSWilliam Juul extern struct mtd_info *get_mtd_device_nm(const char *name); 322932394acSWolfgang Denk 323932394acSWolfgang Denk extern void put_mtd_device(struct mtd_info *mtd); 3244ba692fbSBen Gardiner extern void mtd_get_len_incl_bad(struct mtd_info *mtd, uint64_t offset, 3254ba692fbSBen Gardiner const uint64_t length, uint64_t *len_incl_bad, 3264ba692fbSBen Gardiner int *truncated); 327cfa460adSWilliam Juul /* XXX U-BOOT XXX */ 328932394acSWolfgang Denk #if 0 329932394acSWolfgang Denk struct mtd_notifier { 330932394acSWolfgang Denk void (*add)(struct mtd_info *mtd); 331932394acSWolfgang Denk void (*remove)(struct mtd_info *mtd); 332932394acSWolfgang Denk struct list_head list; 333932394acSWolfgang Denk }; 334932394acSWolfgang Denk 335932394acSWolfgang Denk extern void register_mtd_user (struct mtd_notifier *new); 336932394acSWolfgang Denk extern int unregister_mtd_user (struct mtd_notifier *old); 337932394acSWolfgang Denk #endif 338932394acSWolfgang Denk 339932394acSWolfgang Denk #ifdef CONFIG_MTD_PARTITIONS 340932394acSWolfgang Denk void mtd_erase_callback(struct erase_info *instr); 341932394acSWolfgang Denk #else 342932394acSWolfgang Denk static inline void mtd_erase_callback(struct erase_info *instr) 343932394acSWolfgang Denk { 344932394acSWolfgang Denk if (instr->callback) 345932394acSWolfgang Denk instr->callback(instr); 346932394acSWolfgang Denk } 347932394acSWolfgang Denk #endif 348932394acSWolfgang Denk 349932394acSWolfgang Denk /* 350932394acSWolfgang Denk * Debugging macro and defines 351932394acSWolfgang Denk */ 352932394acSWolfgang Denk #define MTD_DEBUG_LEVEL0 (0) /* Quiet */ 353932394acSWolfgang Denk #define MTD_DEBUG_LEVEL1 (1) /* Audible */ 354932394acSWolfgang Denk #define MTD_DEBUG_LEVEL2 (2) /* Loud */ 355932394acSWolfgang Denk #define MTD_DEBUG_LEVEL3 (3) /* Noisy */ 356932394acSWolfgang Denk 357932394acSWolfgang Denk #ifdef CONFIG_MTD_DEBUG 358dfe64e2cSSergey Lapin #define pr_debug(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args) 3593167c538SScott Wood #define MTDDEBUG(n, args...) \ 360932394acSWolfgang Denk do { \ 361932394acSWolfgang Denk if (n <= CONFIG_MTD_DEBUG_VERBOSE) \ 362932394acSWolfgang Denk printk(KERN_INFO args); \ 363932394acSWolfgang Denk } while(0) 364932394acSWolfgang Denk #else /* CONFIG_MTD_DEBUG */ 365dfe64e2cSSergey Lapin #define pr_debug(args...) 366c45912d8SScott Wood #define MTDDEBUG(n, args...) \ 367c45912d8SScott Wood do { \ 368c45912d8SScott Wood if (0) \ 369c45912d8SScott Wood printk(KERN_INFO args); \ 370c45912d8SScott Wood } while(0) 371932394acSWolfgang Denk #endif /* CONFIG_MTD_DEBUG */ 372dfe64e2cSSergey Lapin #define pr_info(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args) 373dfe64e2cSSergey Lapin #define pr_warn(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args) 374dfe64e2cSSergey Lapin #define pr_err(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args) 375dfe64e2cSSergey Lapin 376dfe64e2cSSergey Lapin static inline int mtd_is_bitflip(int err) { 377dfe64e2cSSergey Lapin return err == -EUCLEAN; 378dfe64e2cSSergey Lapin } 379dfe64e2cSSergey Lapin 380dfe64e2cSSergey Lapin static inline int mtd_is_eccerr(int err) { 381dfe64e2cSSergey Lapin return err == -EBADMSG; 382dfe64e2cSSergey Lapin } 383dfe64e2cSSergey Lapin 384dfe64e2cSSergey Lapin static inline int mtd_is_bitflip_or_eccerr(int err) { 385dfe64e2cSSergey Lapin return mtd_is_bitflip(err) || mtd_is_eccerr(err); 386dfe64e2cSSergey Lapin } 387932394acSWolfgang Denk 388932394acSWolfgang Denk #endif /* __MTD_MTD_H__ */ 389