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;
}
- concat->mtd.oobinfo = subdev[0]->oobinfo;
+ concat->mtd.ecclayout = subdev[0]->ecclayout;
concat->num_subdev = num_devs;
concat->mtd.name = name;
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 */
* 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}}
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;
#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 */
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);
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);
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 */
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);
/*
* 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 "
BUG();
}
+ /*
+ * 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
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)
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;
}
/*
* 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,
/* 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;
/* 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}}
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;
.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,
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;
/**
* 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,
/**
* 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,
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;
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;
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)
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;
}
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);
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.
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,
* @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
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;
* @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 {
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;
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);
* @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
*/
onenand_state_t state;
unsigned char *page_buf;
- struct nand_oobinfo *autooob;
+ struct nand_ecclayout *ecclayout;
- void *bbm;
+ void *bbm;
void *priv;
};
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 */
};
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)
#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;
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__ */
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__ */