]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - include/linux/mtd/mtd.h
Merge branch 'master' of git://git.denx.de/u-boot-nand-flash
[karo-tx-uboot.git] / include / linux / mtd / mtd.h
index 3b18d7d68865c5605e817aec135de9060e6471cb..6f44abdc16102d345e97845f17bc624e5c37eb44 100644 (file)
@@ -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
@@ -55,6 +56,7 @@ struct erase_info {
        u_long priv;
        u_char state;
        struct erase_info *next;
+       int scrub;
 };
 
 struct mtd_erase_region_info {
@@ -64,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
@@ -91,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
  *
@@ -100,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;
@@ -115,7 +101,7 @@ struct mtd_info {
        u_int32_t flags;
        uint64_t size;   /* Total size of the MTD */
 
-       /* "Major" erase size for the device. Naïve users may take this
+       /* "Major" erase size for the device. Naïve users may take this
         * to be the only erase size available, or may use the more detailed
         * information below if they desire
         */
@@ -132,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.
         */
@@ -146,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
@@ -173,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
@@ -200,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 */
@@ -226,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);
@@ -246,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);
@@ -268,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
@@ -295,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__ */