diff options
| author | Tom Rini <trini@ti.com> | 2013-05-31 18:28:47 -0400 | 
|---|---|---|
| committer | Tom Rini <trini@ti.com> | 2013-05-31 18:28:47 -0400 | 
| commit | d6639d10dbfa42dc888f8917012550b632a88959 (patch) | |
| tree | 3c971dcfad4d7ad58570e8d5b0318f58370f9d3d /include/linux/mtd/mtd.h | |
| parent | 3da0e5750b24a9491058df6126c7be577a276c09 (diff) | |
| parent | dfe64e2c89731a3f9950d7acd8681b68df2bae03 (diff) | |
| download | olio-uboot-2014.01-d6639d10dbfa42dc888f8917012550b632a88959.tar.xz olio-uboot-2014.01-d6639d10dbfa42dc888f8917012550b632a88959.zip | |
Merge branch 'master' of git://git.denx.de/u-boot-nand-flash
Diffstat (limited to 'include/linux/mtd/mtd.h')
| -rw-r--r-- | include/linux/mtd/mtd.h | 203 | 
1 files changed, 128 insertions, 75 deletions
| diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 141c96024..6f44abdc1 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -9,7 +9,8 @@  #include <linux/types.h>  #include <div64.h> -#include <linux/mtd/mtd-abi.h> +#include <mtd/mtd-abi.h> +#include <asm/errno.h>  #define MTD_CHAR_MAJOR 90  #define MTD_BLOCK_MAJOR 31 @@ -65,22 +66,6 @@ struct mtd_erase_region_info {  	unsigned long *lockmap;		/* If keeping bitmap of locks */  }; -/* - * oob operation modes - * - * MTD_OOB_PLACE:	oob data are placed at the given offset - * MTD_OOB_AUTO:	oob data are automatically placed at the free areas - *			which are defined by the ecclayout - * MTD_OOB_RAW:		mode to read raw data+oob in one chunk. The oob data - *			is inserted into the data. Thats a raw image of the - *			flash contents. - */ -typedef enum { -	MTD_OOB_PLACE, -	MTD_OOB_AUTO, -	MTD_OOB_RAW, -} mtd_oob_mode_t; -  /**   * struct mtd_oob_ops - oob operation operands   * @mode:	operation mode @@ -92,7 +77,7 @@ typedef enum {   * @ooblen:	number of oob bytes to write/read   * @oobretlen:	number of oob bytes written/read   * @ooboffs:	offset of oob data in the oob area (only relevant when - *		mode = MTD_OOB_PLACE) + *		mode = MTD_OPS_PLACE_OOB or MTD_OPS_RAW)   * @datbuf:	data buffer - if NULL only oob data are read/written   * @oobbuf:	oob data buffer   * @@ -101,7 +86,7 @@ typedef enum {   * OOB area.   */  struct mtd_oob_ops { -	mtd_oob_mode_t	mode; +	unsigned int	mode;  	size_t		len;  	size_t		retlen;  	size_t		ooblen; @@ -133,13 +118,25 @@ struct mtd_info {  	u_int32_t oobsize;   /* Amount of OOB data per block (e.g. 16) */  	u_int32_t oobavail;  /* Available OOB bytes per block */ +	/* +	 * read ops return -EUCLEAN if max number of bitflips corrected on any +	 * one region comprising an ecc step equals or exceeds this value. +	 * Settable by driver, else defaults to ecc_strength.  User can override +	 * in sysfs.  N.B. The meaning of the -EUCLEAN return code has changed; +	 * see Documentation/ABI/testing/sysfs-class-mtd for more detail. +	 */ +	unsigned int bitflip_threshold; +  	/* Kernel-only stuff starts here. */  	const char *name;  	int index; -	/* ecc layout structure pointer - read only ! */ +	/* ECC layout structure pointer - read only! */  	struct nand_ecclayout *ecclayout; +	/* max number of correctible bit errors per ecc step */ +	unsigned int ecc_strength; +  	/* Data for variable erase regions. If numeraseregions is zero,  	 * it means that the whole device has erasesize as given above.  	 */ @@ -147,25 +144,17 @@ struct mtd_info {  	struct mtd_erase_region_info *eraseregions;  	/* -	 * Erase is an asynchronous operation.  Device drivers are supposed -	 * to call instr->callback() whenever the operation completes, even -	 * if it completes with a failure. -	 * Callers are supposed to pass a callback function and wait for it -	 * to be called before writing to the block. +	 * Do not call via these pointers, use corresponding mtd_*() +	 * wrappers instead.  	 */ -	int (*erase) (struct mtd_info *mtd, struct erase_info *instr); - -	/* This stuff for eXecute-In-Place */ -	/* phys is optional and may be set to NULL */ -	int (*point) (struct mtd_info *mtd, loff_t from, size_t len, +	int (*_erase) (struct mtd_info *mtd, struct erase_info *instr); +	int (*_point) (struct mtd_info *mtd, loff_t from, size_t len,  			size_t *retlen, void **virt, phys_addr_t *phys); - -	/* We probably shouldn't allow XIP if the unpoint isn't a NULL */ -	void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len); - - -	int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -	int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); +	void (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len); +	int (*_read) (struct mtd_info *mtd, loff_t from, size_t len, +		     size_t *retlen, u_char *buf); +	int (*_write) (struct mtd_info *mtd, loff_t to, size_t len, +		      size_t *retlen, const u_char *buf);  	/* In blackbox flight recorder like scenarios we want to make successful  	   writes in interrupt context. panic_write() is only intended to be @@ -174,24 +163,35 @@ struct mtd_info {  	   longer, this function can break locks and delay to ensure the write  	   succeeds (but not sleep). */ -	int (*panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); +	int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); -	int (*read_oob) (struct mtd_info *mtd, loff_t from, +	int (*_read_oob) (struct mtd_info *mtd, loff_t from,  			 struct mtd_oob_ops *ops); -	int (*write_oob) (struct mtd_info *mtd, loff_t to, +	int (*_write_oob) (struct mtd_info *mtd, loff_t to,  			 struct mtd_oob_ops *ops); - +	int (*_get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, +				   size_t len); +	int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, +				   size_t len, size_t *retlen, u_char *buf); +	int (*_get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, +				   size_t len); +	int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from, +				   size_t len, size_t *retlen, u_char *buf); +	int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to, size_t len, +				    size_t *retlen, u_char *buf); +	int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, +				   size_t len); +	void (*_sync) (struct mtd_info *mtd); +	int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); +	int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); +	int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs); +	int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);  	/* -	 * Methods to access the protection register area, present in some -	 * flash devices. The user data is one time programmable but the -	 * factory data is read only. +	 * If the driver is something smart, like UBI, it may need to maintain +	 * its own reference counting. The below functions are only for driver.  	 */ -	int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len); -	int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -	int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len); -	int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -	int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -	int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len); +	int (*_get_device) (struct mtd_info *mtd); +	void (*_put_device) (struct mtd_info *mtd);  /* XXX U-BOOT XXX */  #if 0 @@ -201,18 +201,6 @@ struct mtd_info {  	*/  	int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);  #endif - -	/* Sync */ -	void (*sync) (struct mtd_info *mtd); - -	/* Chip-supported device locking */ -	int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); -	int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); - -	/* Bad block management functions */ -	int (*block_isbad) (struct mtd_info *mtd, loff_t ofs); -	int (*block_markbad) (struct mtd_info *mtd, loff_t ofs); -  /* XXX U-BOOT XXX */  #if 0  	struct notifier_block reboot_notifier;  /* default mode before reboot */ @@ -227,15 +215,59 @@ struct mtd_info {  	struct module *owner;  	int usecount; - -	/* If the driver is something smart, like UBI, it may need to maintain -	 * its own reference counting. The below functions are only for driver. -	 * The driver may register its callbacks. These callbacks are not -	 * supposed to be called by MTD users */ -	int (*get_device) (struct mtd_info *mtd); -	void (*put_device) (struct mtd_info *mtd);  }; +int mtd_erase(struct mtd_info *mtd, struct erase_info *instr); +int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, +	     u_char *buf); +int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, +	      const u_char *buf); +int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, +		    const u_char *buf); + +int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); + +static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to, +				struct mtd_oob_ops *ops) +{ +	ops->retlen = ops->oobretlen = 0; +	if (!mtd->_write_oob) +		return -EOPNOTSUPP; +	if (!(mtd->flags & MTD_WRITEABLE)) +		return -EROFS; +	return mtd->_write_oob(mtd, to, ops); +} + +int mtd_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf, +			   size_t len); +int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, +			   size_t *retlen, u_char *buf); +int mtd_get_user_prot_info(struct mtd_info *mtd, struct otp_info *buf, +			   size_t len); +int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, +			   size_t *retlen, u_char *buf); +int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, +			    size_t *retlen, u_char *buf); +int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len); + +/* XXX U-BOOT XXX */ +#if 0 +int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, +	       unsigned long count, loff_t to, size_t *retlen); +#endif + +static inline void mtd_sync(struct mtd_info *mtd) +{ +	if (mtd->_sync) +		mtd->_sync(mtd); +} + +int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); +int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); +int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len); +int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs); +int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs); +  static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd)  {  	do_div(sz, mtd->erasesize); @@ -247,6 +279,16 @@ static inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd)  	return do_div(sz, mtd->erasesize);  } +static inline int mtd_has_oob(const struct mtd_info *mtd) +{ +	return mtd->_read_oob && mtd->_write_oob; +} + +static inline int mtd_can_have_bb(const struct mtd_info *mtd) +{ +	return !!mtd->_block_isbad; +} +  	/* Kernel-side ioctl definitions */  extern int add_mtd_device(struct mtd_info *mtd); @@ -269,12 +311,6 @@ struct mtd_notifier {  extern void register_mtd_user (struct mtd_notifier *new);  extern int unregister_mtd_user (struct mtd_notifier *old); - -int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, -		       unsigned long count, loff_t to, size_t *retlen); - -int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs, -		      unsigned long count, loff_t from, size_t *retlen);  #endif  #ifdef CONFIG_MTD_PARTITIONS @@ -296,17 +332,34 @@ static inline void mtd_erase_callback(struct erase_info *instr)  #define MTD_DEBUG_LEVEL3	(3)	/* Noisy   */  #ifdef CONFIG_MTD_DEBUG +#define pr_debug(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args)  #define MTDDEBUG(n, args...)				\  	do {						\  		if (n <= CONFIG_MTD_DEBUG_VERBOSE)	\  			printk(KERN_INFO args);		\  	} while(0)  #else /* CONFIG_MTD_DEBUG */ +#define pr_debug(args...)  #define MTDDEBUG(n, args...)				\  	do {						\  		if (0)					\  			printk(KERN_INFO args);		\  	} while(0)  #endif /* CONFIG_MTD_DEBUG */ +#define pr_info(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args) +#define pr_warn(args...)	MTDDEBUG(MTD_DEBUG_LEVEL0, args) +#define pr_err(args...)		MTDDEBUG(MTD_DEBUG_LEVEL0, args) + +static inline int mtd_is_bitflip(int err) { +	return err == -EUCLEAN; +} + +static inline int mtd_is_eccerr(int err) { +	return err == -EBADMSG; +} + +static inline int mtd_is_bitflip_or_eccerr(int err) { +	return mtd_is_bitflip(err) || mtd_is_eccerr(err); +}  #endif /* __MTD_MTD_H__ */ |