[MTD] NAND Replace oobinfo by ecclayout
authorThomas Gleixner <tglx@cruncher.tec.linutronix.de>
Sat, 27 May 2006 20:16:10 +0000 (22:16 +0200)
committerThomas Gleixner <tglx@cruncher.tec.linutronix.de>
Mon, 29 May 2006 13:06:50 +0000 (15:06 +0200)
The nand_oobinfo structure is not fitting the newer error correction
demands anymore. Replace it by struct nand_ecclayout and fixup the users
all over the place. Keep the nand_oobinfo based ioctl for user space
compability reasons.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
20 files changed:
drivers/mtd/mtdchar.c
drivers/mtd/mtdconcat.c
drivers/mtd/mtdpart.c
drivers/mtd/nand/diskonchip.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/ndfc.c
drivers/mtd/nand/rtc_from4.c
drivers/mtd/nand/s3c2410.c
drivers/mtd/nand/sharpsl.c
drivers/mtd/onenand/onenand_base.c
fs/jffs2/jffs2_fs_sb.h
fs/jffs2/wbuf.c
include/linux/mtd/inftl.h
include/linux/mtd/mtd.h
include/linux/mtd/nand.h
include/linux/mtd/nftl.h
include/linux/mtd/onenand.h
include/linux/mtd/partitions.h
include/mtd/mtd-abi.h
include/mtd/mtd-user.h

index 608f7af..e75ec5f 100644 (file)
@@ -512,14 +512,36 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
                break;
        }
 
+       /* Legacy interface */
        case MEMGETOOBSEL:
        {
-               if (copy_to_user(argp, mtd->oobinfo,
-                                sizeof(struct nand_oobinfo)))
+               struct nand_oobinfo oi;
+
+               if (!mtd->ecclayout)
+                       return -EOPNOTSUPP;
+               if (mtd->ecclayout->eccbytes > ARRAY_SIZE(oi.eccpos))
+                       return -EINVAL;
+
+               oi.useecc = MTD_NANDECC_AUTOPLACE;
+               memcpy(&oi.eccpos, mtd->ecclayout->eccpos, sizeof(oi.eccpos));
+               memcpy(&oi.oobfree, mtd->ecclayout->oobfree,
+                      sizeof(oi.oobfree));
+
+               if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo)))
                        return -EFAULT;
                break;
        }
 
+       case ECCGETLAYOUT:
+
+               if (!mtd->ecclayout)
+                       return -EOPNOTSUPP;
+
+               if (copy_to_user(argp, &mtd->ecclayout,
+                                sizeof(struct nand_ecclayout)))
+                       return -EFAULT;
+               break;
+
        case MEMGETBADBLOCK:
        {
                loff_t offs;
index 699fce7..ec15abc 100644 (file)
@@ -766,7 +766,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[],       /* subdevices to c
 
        }
 
-       concat->mtd.oobinfo = subdev[0]->oobinfo;
+       concat->mtd.ecclayout = subdev[0]->ecclayout;
 
        concat->num_subdev = num_devs;
        concat->mtd.name = name;
index b6b2189..6d7639b 100644 (file)
@@ -434,7 +434,7 @@ int add_mtd_partitions(struct mtd_info *master,
                                parts[i].name);
                }
 
-               slave->mtd.oobinfo = master->oobinfo;
+               slave->mtd.ecclayout = master->ecclayout;
 
                if(parts[i].mtdp)
                {       /* store the object pointer (caller may or may not register it */
index 82262a4..463e12c 100644 (file)
@@ -1058,8 +1058,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat,
  * safer.  The only problem with it is that any code that parses oobfree must
  * be able to handle out-of-order segments.
  */
-static struct nand_oobinfo doc200x_oobinfo = {
-       .useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout doc200x_oobinfo = {
        .eccbytes = 6,
        .eccpos = {0, 1, 2, 3, 4, 5},
        .oobfree = {{8, 8}, {6, 2}}
@@ -1662,7 +1661,7 @@ static int __init doc_probe(unsigned long physadr)
        nand->ecc.calculate     = doc200x_calculate_ecc;
        nand->ecc.correct       = doc200x_correct_data;
 
-       nand->autooob           = &doc200x_oobinfo;
+       nand->ecc.layout        = &doc200x_oobinfo;
        nand->ecc.mode          = NAND_ECC_HW_SYNDROME;
        nand->ecc.size          = 512;
        nand->ecc.bytes         = 6;
index 20f79fe..e922b82 100644 (file)
 #endif
 
 /* Define default oob placement schemes for large and small page devices */
-static struct nand_oobinfo nand_oob_8 = {
-       .useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout nand_oob_8 = {
        .eccbytes = 3,
        .eccpos = {0, 1, 2},
-       .oobfree = {{3, 2}, {6, 2}}
+       .oobfree = {
+               {.offset = 3,
+                .length = 2},
+               {.offset = 6,
+                .length = 2}}
 };
 
-static struct nand_oobinfo nand_oob_16 = {
-       .useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout nand_oob_16 = {
        .eccbytes = 6,
        .eccpos = {0, 1, 2, 3, 6, 7},
-       .oobfree = {{8, 8}}
+       .oobfree = {
+               {.offset = 8,
+                . length = 8}}
 };
 
-static struct nand_oobinfo nand_oob_64 = {
-       .useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout nand_oob_64 = {
        .eccbytes = 24,
        .eccpos = {
                   40, 41, 42, 43, 44, 45, 46, 47,
                   48, 49, 50, 51, 52, 53, 54, 55,
                   56, 57, 58, 59, 60, 61, 62, 63},
-       .oobfree = {{2, 38}}
+       .oobfree = {
+               {.offset = 2,
+                .length = 38}}
 };
 
 /* This is used for padding purposes in nand_write_oob */
@@ -749,7 +754,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
        uint8_t *p = buf;
        uint8_t *ecc_calc = chip->buffers.ecccalc;
        uint8_t *ecc_code = chip->buffers.ecccode;
-       int *eccpos = chip->autooob->eccpos;
+       int *eccpos = chip->ecc.layout->eccpos;
 
        chip->read_buf(mtd, buf, mtd->writesize);
        chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -795,7 +800,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
        uint8_t *p = buf;
        uint8_t *ecc_calc = chip->buffers.ecccalc;
        uint8_t *ecc_code = chip->buffers.ecccode;
-       int *eccpos = chip->autooob->eccpos;
+       int *eccpos = chip->ecc.layout->eccpos;
 
        for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
                chip->ecc.hwctl(mtd, NAND_ECC_READ);
@@ -1198,7 +1203,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
        int eccsteps = chip->ecc.steps;
        uint8_t *ecc_calc = chip->buffers.ecccalc;
        const uint8_t *p = buf;
-       int *eccpos = chip->autooob->eccpos;
+       int *eccpos = chip->ecc.layout->eccpos;
 
        if (chip->ecc.mode != NAND_ECC_NONE) {
                /* Software ecc calculation */
@@ -1227,7 +1232,7 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
        int eccsteps = chip->ecc.steps;
        uint8_t *ecc_calc = chip->buffers.ecccalc;
        const uint8_t *p = buf;
-       int *eccpos = chip->autooob->eccpos;
+       int *eccpos = chip->ecc.layout->eccpos;
 
        for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
                chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
@@ -2124,16 +2129,16 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
        /*
         * If no default placement scheme is given, select an appropriate one
         */
-       if (!chip->autooob) {
+       if (!chip->ecc.layout) {
                switch (mtd->oobsize) {
                case 8:
-                       chip->autooob = &nand_oob_8;
+                       chip->ecc.layout = &nand_oob_8;
                        break;
                case 16:
-                       chip->autooob = &nand_oob_16;
+                       chip->ecc.layout = &nand_oob_16;
                        break;
                case 64:
-                       chip->autooob = &nand_oob_64;
+                       chip->ecc.layout = &nand_oob_64;
                        break;
                default:
                        printk(KERN_WARNING "No oob scheme defined for "
@@ -2198,6 +2203,15 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
        }
 
        /*
+        * The number of bytes available for a client to place data into
+        * the out of band area
+        */
+       chip->ecc.layout->oobavail = 0;
+       for (i = 0; chip->ecc.layout->oobfree[i].length; i++)
+               chip->ecc.layout->oobavail +=
+                       chip->ecc.layout->oobfree[i].length;
+
+       /*
         * Set the number of read / write steps for one page depending on ECC
         * mode
         */
@@ -2236,8 +2250,8 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
        mtd->block_isbad = nand_block_isbad;
        mtd->block_markbad = nand_block_markbad;
 
-       /* and make the autooob the default one */
-       mtd->oobinfo = chip->autooob;
+       /* propagate ecc.layout to mtd_info */
+       mtd->ecclayout = chip->ecc.layout;
 
        /* Check, if we should skip the bad block table scan */
        if (chip->options & NAND_SKIP_BBTSCAN)
index 5790d63..551702d 100644 (file)
@@ -168,7 +168,7 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
        chip->ecc.mode = NAND_ECC_HW;
        chip->ecc.size = 256;
        chip->ecc.bytes = 3;
-       chip->autooob = mtd->pl_chip->oobinfo;
+       chip->ecclayout = mtd->pl_chip->ecclayout;
        mtd->mtd.priv = chip;
        mtd->mtd.owner = THIS_MODULE;
 }
index de6de91..f8c4964 100644 (file)
@@ -142,8 +142,7 @@ static struct rs_control *rs_decoder;
 /*
  *      hardware specific Out Of Band information
  */
-static struct nand_oobinfo rtc_from4_nand_oobinfo = {
-       .useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout rtc_from4_nand_oobinfo = {
        .eccbytes = 32,
        .eccpos = {
                   0, 1, 2, 3, 4, 5, 6, 7,
@@ -574,7 +573,7 @@ static int __init rtc_from4_init(void)
        /* return the status of extra status and ECC checks */
        this->errstat = rtc_from4_errstat;
        /* set the nand_oobinfo to support FPGA H/W error detection */
-       this->autooob = &rtc_from4_nand_oobinfo;
+       this->ecc.layout = &rtc_from4_nand_oobinfo;
        this->ecc.hwctl = rtc_from4_enable_hwecc;
        this->ecc.calculate = rtc_from4_calculate_ecc;
        this->ecc.correct = rtc_from4_correct_data;
index 215227d..8429793 100644 (file)
@@ -76,8 +76,7 @@ static int hardware_ecc = 0;
 /* new oob placement block for use with hardware ecc generation
  */
 
-static struct nand_oobinfo nand_hw_eccoob = {
-       .useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout nand_hw_eccoob = {
        .eccbytes = 3,
        .eccpos = {0, 1, 2},
        .oobfree = {{8, 8}}
@@ -502,7 +501,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
                chip->ecc.mode      = NAND_ECC_HW;
                chip->ecc.size      = 512;
                chip->ecc.bytes     = 3;
-               chip->autooob       = &nand_hw_eccoob;
+               chip->ecc.layout    = &nand_hw_eccoob;
 
                if (info->is_s3c2440) {
                        chip->ecc.hwctl     = s3c2440_nand_enable_hwecc;
index 45a1da7..2174365 100644 (file)
@@ -115,8 +115,7 @@ static struct nand_bbt_descr sharpsl_akita_bbt = {
        .pattern = scan_ff_pattern
 };
 
-static struct nand_oobinfo akita_oobinfo = {
-       .useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout akita_oobinfo = {
        .eccbytes = 24,
        .eccpos = {
                   0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11,
@@ -202,7 +201,7 @@ static int __init sharpsl_nand_init(void)
        this->badblock_pattern = &sharpsl_bbt;
        if (machine_is_akita() || machine_is_borzoi()) {
                this->badblock_pattern = &sharpsl_akita_bbt;
-               this->autooob = &akita_oobinfo;
+               this->ecc.layout = &akita_oobinfo;
        }
        this->ecc.hwctl = sharpsl_nand_enable_hwecc;
        this->ecc.calculate = sharpsl_nand_calculate_ecc;
index b24bfa6..a0d3f01 100644 (file)
@@ -23,8 +23,7 @@
 /**
  * onenand_oob_64 - oob info for large (2KB) page
  */
-static struct nand_oobinfo onenand_oob_64 = {
-       .useecc         = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout onenand_oob_64 = {
        .eccbytes       = 20,
        .eccpos         = {
                8, 9, 10, 11, 12,
@@ -41,8 +40,7 @@ static struct nand_oobinfo onenand_oob_64 = {
 /**
  * onenand_oob_32 - oob info for middle (1KB) page
  */
-static struct nand_oobinfo onenand_oob_32 = {
-       .useecc         = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout onenand_oob_32 = {
        .eccbytes       = 10,
        .eccpos         = {
                8, 9, 10, 11, 12,
@@ -1747,22 +1745,22 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
 
        switch (mtd->oobsize) {
        case 64:
-               this->autooob = &onenand_oob_64;
+               this->ecclayout = &onenand_oob_64;
                break;
 
        case 32:
-               this->autooob = &onenand_oob_32;
+               this->ecclayout = &onenand_oob_32;
                break;
 
        default:
                printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n",
                        mtd->oobsize);
                /* To prevent kernel oops */
-               this->autooob = &onenand_oob_32;
+               this->ecclayout = &onenand_oob_32;
                break;
        }
 
-       mtd->oobinfo = this->autooob;
+       mtd->ecclayout = this->ecclayout;
 
        /* Fill in remaining MTD driver data */
        mtd->type = MTD_NANDFLASH;
index 272fbea..506690c 100644 (file)
@@ -107,7 +107,7 @@ struct jffs2_sb_info {
        struct rw_semaphore wbuf_sem;   /* Protects the write buffer */
 
        /* Information about out-of-band area usage... */
-       struct nand_oobinfo *oobinfo;
+       struct nand_ecclayout *ecclayout;
        uint32_t badblock_pos;
        uint32_t fsdata_pos;
        uint32_t fsdata_len;
index dc275ce..c6a62e1 100644 (file)
@@ -1140,18 +1140,9 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *
        return 1;
 }
 
-#define NAND_JFFS2_OOB16_FSDALEN       8
-
-static struct nand_oobinfo jffs2_oobinfo_docecc = {
-       .useecc = MTD_NANDECC_PLACE,
-       .eccbytes = 6,
-       .eccpos = {0,1,2,3,4,5}
-};
-
-
 static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c)
 {
-       struct nand_oobinfo *oinfo = c->mtd->oobinfo;
+       struct nand_ecclayout *oinfo = c->mtd->ecclayout;
 
        /* Do this only, if we have an oob buffer */
        if (!c->mtd->oobsize)
@@ -1161,33 +1152,23 @@ static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c)
        c->cleanmarker_size = 0;
 
        /* Should we use autoplacement ? */
-       if (oinfo && oinfo->useecc == MTD_NANDECC_AUTOPLACE) {
-               D1(printk(KERN_DEBUG "JFFS2 using autoplace on NAND\n"));
-               /* Get the position of the free bytes */
-               if (!oinfo->oobfree[0][1]) {
-                       printk (KERN_WARNING "jffs2_nand_set_oobinfo(): Eeep. Autoplacement selected and no empty space in oob\n");
-                       return -ENOSPC;
-               }
-               c->fsdata_pos = oinfo->oobfree[0][0];
-               c->fsdata_len = oinfo->oobfree[0][1];
-               if (c->fsdata_len > 8)
-                       c->fsdata_len = 8;
-       } else {
-               /* This is just a legacy fallback and should go away soon */
-               switch(c->mtd->ecctype) {
-               case MTD_ECC_RS_DiskOnChip:
-                       printk(KERN_WARNING "JFFS2 using DiskOnChip hardware ECC without autoplacement. Fix it!\n");
-                       c->oobinfo = &jffs2_oobinfo_docecc;
-                       c->fsdata_pos = 6;
-                       c->fsdata_len = NAND_JFFS2_OOB16_FSDALEN;
-                       c->badblock_pos = 15;
-                       break;
+       if (!oinfo) {
+               D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n"));
+               return -EINVAL;
+       }
 
-               default:
-                       D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n"));
-                       return -EINVAL;
-               }
+       D1(printk(KERN_DEBUG "JFFS2 using autoplace on NAND\n"));
+       /* Get the position of the free bytes */
+       if (!oinfo->oobfree[0].length) {
+               printk (KERN_WARNING "jffs2_nand_set_oobinfo(): Eeep."
+                       " Autoplacement selected and no empty space in oob\n");
+               return -ENOSPC;
        }
+       c->fsdata_pos = oinfo->oobfree[0].offset;
+       c->fsdata_len = oinfo->oobfree[0].length;
+       if (c->fsdata_len > 8)
+               c->fsdata_len = 8;
+
        return 0;
 }
 
index d7eaa40..6977780 100644 (file)
@@ -46,7 +46,7 @@ struct INFTLrecord {
         unsigned int nb_blocks;                /* number of physical blocks */
         unsigned int nb_boot_blocks;   /* number of blocks used by the bios */
         struct erase_info instr;
-        struct nand_oobinfo oobinfo;
+        struct nand_ecclayout oobinfo;
 };
 
 int INFTL_mount(struct INFTLrecord *s);
index 8429da5..48a9df2 100644 (file)
@@ -101,8 +101,8 @@ struct mtd_info {
        char *name;
        int index;
 
-       /* oobinfo structure pointer - read only ! */
-       struct nand_oobinfo *oobinfo;
+       /* ecc layout structure pointer - read only ! */
+       struct nand_ecclayout *ecclayout;
 
        /* Data for variable erase regions. If numeraseregions is zero,
         * it means that the whole device has erasesize as given above.
index fd46bcf..dc2bf1b 100644 (file)
@@ -244,6 +244,7 @@ struct nand_ecc_ctrl {
        int                     total;
        int                     prepad;
        int                     postpad;
+       struct nand_ecclayout   *layout;
        void                    (*hwctl)(struct mtd_info *mtd, int mode);
        int                     (*calculate)(struct mtd_info *mtd,
                                             const uint8_t *dat,
@@ -318,7 +319,7 @@ struct nand_buffers {
  * @chipsize:          [INTERN] the size of one chip for multichip arrays
  * @pagemask:          [INTERN] page number mask = number of (pages / chip) - 1
  * @pagebuf:           [INTERN] holds the pagenumber which is currently in data_buf
- * @autooob:           [REPLACEABLE] the default (auto)placement scheme
+ * @ecclayout:         [REPLACEABLE] the default ecc placement scheme
  * @bbt:               [INTERN] bad block table pointer
  * @bbt_td:            [REPLACEABLE] bad block table descriptor for flash lookup
  * @bbt_md:            [REPLACEABLE] bad block table mirror descriptor
@@ -368,7 +369,7 @@ struct nand_chip {
 
        uint8_t         *oob_poi;
        struct nand_hw_control  *controller;
-       struct nand_oobinfo     *autooob;
+       struct nand_ecclayout   *ecclayout;
 
        struct nand_ecc_ctrl ecc;
        struct nand_buffers buffers;
@@ -522,7 +523,7 @@ extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
  * @partitions:                mtd partition list
  * @chip_delay:                R/B delay value in us
  * @options:           Option flags, e.g. 16bit buswidth
- * @oobinfo:           oob info structure (ecc placement)
+ * @ecclayout:         ecc layout info structure
  * @priv:              hardware controller specific settings
  */
 struct platform_nand_chip {
@@ -530,7 +531,7 @@ struct platform_nand_chip {
        int                     chip_offset;
        int                     nr_partitions;
        struct mtd_partition    *partitions;
-       struct nand_oobinfo     *oobinfo;
+       struct nand_ecclayout   *ecclayout;
        int                     chip_delay;
        unsigned int            options;
        void                    *priv;
index d35d2c2..bcf2fb3 100644 (file)
@@ -37,7 +37,7 @@ struct NFTLrecord {
         unsigned int nb_blocks;                /* number of physical blocks */
         unsigned int nb_boot_blocks;   /* number of blocks used by the bios */
         struct erase_info instr;
-       struct nand_oobinfo oobinfo;
+       struct nand_ecclayout oobinfo;
 };
 
 int NFTL_mount(struct NFTLrecord *s);
index 3f5919f..9ce9a48 100644 (file)
@@ -77,7 +77,7 @@ struct onenand_bufferram {
  * @param chip_lock    [INTERN] spinlock used to protect access to this structure and the chip
  * @param wq           [INTERN] wait queue to sleep on if a OneNAND operation is in progress
  * @param state                [INTERN] the current state of the OneNAND device
- * @param autooob      [REPLACEABLE] the default (auto)placement scheme
+ * @param ecclayout    [REPLACEABLE] the default ecc placement scheme
  * @param bbm          [REPLACEABLE] pointer to Bad Block Management
  * @param priv         [OPTIONAL] pointer to private chip date
  */
@@ -113,9 +113,9 @@ struct onenand_chip {
        onenand_state_t         state;
        unsigned char           *page_buf;
 
-       struct nand_oobinfo     *autooob;
+       struct nand_ecclayout   *ecclayout;
 
-       void                    *bbm;
+       void                    *bbm;
 
        void                    *priv;
 };
index b03f512..da6b3d6 100644 (file)
@@ -41,7 +41,7 @@ struct mtd_partition {
        u_int32_t size;                 /* partition size */
        u_int32_t offset;               /* offset within the master MTD space */
        u_int32_t mask_flags;           /* master MTD flags to mask out for this partition */
-       struct nand_oobinfo *oobsel;    /* out of band layout for this partition (NAND only)*/
+       struct nand_ecclayout *ecclayout;       /* out of band layout for this partition (NAND only)*/
        struct mtd_info **mtdp;         /* pointer to store the MTD object */
 };
 
index 1e09e4c..54c673f 100644 (file)
@@ -82,12 +82,12 @@ struct otp_info {
        uint32_t locked;
 };
 
-#define MEMGETINFO              _IOR('M', 1, struct mtd_info_user)
-#define MEMERASE                _IOW('M', 2, struct erase_info_user)
-#define MEMWRITEOOB             _IOWR('M', 3, struct mtd_oob_buf)
-#define MEMREADOOB              _IOWR('M', 4, struct mtd_oob_buf)
-#define MEMLOCK                 _IOW('M', 5, struct erase_info_user)
-#define MEMUNLOCK               _IOW('M', 6, struct erase_info_user)
+#define MEMGETINFO             _IOR('M', 1, struct mtd_info_user)
+#define MEMERASE               _IOW('M', 2, struct erase_info_user)
+#define MEMWRITEOOB            _IOWR('M', 3, struct mtd_oob_buf)
+#define MEMREADOOB             _IOWR('M', 4, struct mtd_oob_buf)
+#define MEMLOCK                        _IOW('M', 5, struct erase_info_user)
+#define MEMUNLOCK              _IOW('M', 6, struct erase_info_user)
 #define MEMGETREGIONCOUNT      _IOR('M', 7, int)
 #define MEMGETREGIONINFO       _IOWR('M', 8, struct region_info_user)
 #define MEMSETOOBSEL           _IOW('M', 9, struct nand_oobinfo)
@@ -97,8 +97,13 @@ struct otp_info {
 #define OTPSELECT              _IOR('M', 13, int)
 #define OTPGETREGIONCOUNT      _IOW('M', 14, int)
 #define OTPGETREGIONINFO       _IOW('M', 15, struct otp_info)
-#define OTPLOCK                _IOR('M', 16, struct otp_info)
+#define OTPLOCK                        _IOR('M', 16, struct otp_info)
+#define ECCGETLAYOUT           _IOR('M', 17, struct nand_ecclayout)
 
+/*
+ * Obsolete legacy interface. Keep it in order not to break userspace
+ * interfaces
+ */
 struct nand_oobinfo {
        uint32_t useecc;
        uint32_t eccbytes;
@@ -106,4 +111,21 @@ struct nand_oobinfo {
        uint32_t eccpos[32];
 };
 
+struct nand_oobfree {
+       uint32_t offset;
+       uint32_t length;
+};
+
+#define MTD_MAX_OOBFREE_ENTRIES        8
+/*
+ * ECC layout control structure. Exported to userspace for
+ * diagnosis and to allow creation of raw images
+ */
+struct nand_ecclayout {
+       uint32_t eccbytes;
+       uint32_t eccpos[64];
+       uint32_t oobavail;
+       struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
+};
+
 #endif /* __MTD_ABI_H__ */
index 1c13fc7..713f34d 100644 (file)
@@ -16,5 +16,6 @@ typedef struct mtd_info_user mtd_info_t;
 typedef struct erase_info_user erase_info_t;
 typedef struct region_info_user region_info_t;
 typedef struct nand_oobinfo nand_oobinfo_t;
+typedef struct nand_ecclayout nand_ecclayout_t;
 
 #endif /* __MTD_USER_H__ */