Loading drivers/mtd/mtdconcat.c +1 −0 Original line number Diff line number Diff line Loading @@ -772,6 +772,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c concat->mtd.ecc_stats.badblocks += subdev[i]->ecc_stats.badblocks; if (concat->mtd.writesize != subdev[i]->writesize || concat->mtd.subpage_sft != subdev[i]->subpage_sft || concat->mtd.oobsize != subdev[i]->oobsize || concat->mtd.ecctype != subdev[i]->ecctype || concat->mtd.eccsize != subdev[i]->eccsize || Loading drivers/mtd/mtdpart.c +1 −0 Original line number Diff line number Diff line Loading @@ -340,6 +340,7 @@ int add_mtd_partitions(struct mtd_info *master, slave->mtd.oobsize = master->oobsize; slave->mtd.ecctype = master->ecctype; slave->mtd.eccsize = master->eccsize; slave->mtd.subpage_sft = master->subpage_sft; slave->mtd.name = parts[i].name; slave->mtd.bank_size = master->bank_size; Loading drivers/mtd/nand/nand_base.c +44 −9 Original line number Diff line number Diff line Loading @@ -1590,7 +1590,7 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, return NULL; } #define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0 #define NOTALIGNED(x) (x & (chip->subpagesize - 1)) != 0 /** * nand_do_write_ops - [Internal] NAND write with ECC Loading @@ -1603,15 +1603,16 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) { int chipnr, realpage, page, blockmask; int chipnr, realpage, page, blockmask, column; struct nand_chip *chip = mtd->priv; uint32_t writelen = ops->len; uint8_t *oob = ops->oobbuf; uint8_t *buf = ops->datbuf; int bytes = mtd->writesize; int ret; int ret, subpage; ops->retlen = 0; if (!writelen) return 0; /* reject writes, which are not page aligned */ if (NOTALIGNED(to) || NOTALIGNED(ops->len)) { Loading @@ -1620,8 +1621,11 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, return -EINVAL; } if (!writelen) return 0; column = to & (mtd->writesize - 1); subpage = column || (writelen & (mtd->writesize - 1)); if (subpage && oob) return -EINVAL; chipnr = (int)(to >> chip->chip_shift); chip->select_chip(mtd, chipnr); Loading @@ -1644,12 +1648,24 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, memset(chip->oob_poi, 0xff, mtd->oobsize); while(1) { int bytes = mtd->writesize; int cached = writelen > bytes && page != blockmask; uint8_t *wbuf = buf; /* Partial page write ? */ if (unlikely(column || writelen < (mtd->writesize - 1))) { cached = 0; bytes = min_t(int, bytes - column, (int) writelen); chip->pagebuf = -1; memset(chip->buffers->databuf, 0xff, mtd->writesize); memcpy(&chip->buffers->databuf[column], buf, bytes); wbuf = chip->buffers->databuf; } if (unlikely(oob)) oob = nand_fill_oob(chip, oob, ops); ret = chip->write_page(mtd, chip, buf, page, cached, ret = chip->write_page(mtd, chip, wbuf, page, cached, (ops->mode == MTD_OOB_RAW)); if (ret) break; Loading @@ -1658,6 +1674,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, if (!writelen) break; column = 0; buf += bytes; realpage++; Loading Loading @@ -2201,8 +2218,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, /* Newer devices have all the information in additional id bytes */ if (!type->pagesize) { int extid; /* The 3rd id byte contains non relevant data ATM */ extid = chip->read_byte(mtd); /* The 3rd id byte holds MLC / multichip data */ chip->cellinfo = chip->read_byte(mtd); /* The 4th id byte is the important one */ extid = chip->read_byte(mtd); /* Calc pagesize */ Loading Loading @@ -2482,6 +2499,24 @@ int nand_scan_tail(struct mtd_info *mtd) } chip->ecc.total = chip->ecc.steps * chip->ecc.bytes; /* * Allow subpage writes up to ecc.steps. Not possible for MLC * FLASH. */ if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) { switch(chip->ecc.steps) { case 2: mtd->subpage_sft = 1; break; case 4: case 8: mtd->subpage_sft = 2; break; } } chip->subpagesize = mtd->writesize >> mtd->subpage_sft; /* Initialize state */ chip->state = FL_READY; Loading include/linux/mtd/mtd.h +2 −0 Original line number Diff line number Diff line Loading @@ -200,6 +200,8 @@ struct mtd_info { /* ECC status information */ struct mtd_ecc_stats ecc_stats; /* Subpage shift (NAND) */ int subpage_sft; void *priv; Loading include/linux/mtd/nand.h +9 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,9 @@ typedef enum { * for all large page devices, as they do not support * autoincrement.*/ #define NAND_NO_READRDY 0x00000100 /* Chip does not allow subpage writes */ #define NAND_NO_SUBPAGE_WRITE 0x00000200 /* Options valid for Samsung large page devices */ #define NAND_SAMSUNG_LP_OPTIONS \ Loading Loading @@ -193,6 +196,9 @@ typedef enum { /* Nand scan has allocated controller struct */ #define NAND_CONTROLLER_ALLOC 0x80000000 /* Cell info constants */ #define NAND_CI_CHIPNR_MSK 0x03 #define NAND_CI_CELLTYPE_MSK 0x0C /* * nand_state_t - chip states Loading Loading @@ -341,6 +347,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 * @subpagesize: [INTERN] holds the subpagesize * @ecclayout: [REPLACEABLE] the default ecc placement scheme * @bbt: [INTERN] bad block table pointer * @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup Loading Loading @@ -388,6 +395,8 @@ struct nand_chip { unsigned long chipsize; int pagemask; int pagebuf; int subpagesize; uint8_t cellinfo; int badblockpos; nand_state_t state; Loading Loading
drivers/mtd/mtdconcat.c +1 −0 Original line number Diff line number Diff line Loading @@ -772,6 +772,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c concat->mtd.ecc_stats.badblocks += subdev[i]->ecc_stats.badblocks; if (concat->mtd.writesize != subdev[i]->writesize || concat->mtd.subpage_sft != subdev[i]->subpage_sft || concat->mtd.oobsize != subdev[i]->oobsize || concat->mtd.ecctype != subdev[i]->ecctype || concat->mtd.eccsize != subdev[i]->eccsize || Loading
drivers/mtd/mtdpart.c +1 −0 Original line number Diff line number Diff line Loading @@ -340,6 +340,7 @@ int add_mtd_partitions(struct mtd_info *master, slave->mtd.oobsize = master->oobsize; slave->mtd.ecctype = master->ecctype; slave->mtd.eccsize = master->eccsize; slave->mtd.subpage_sft = master->subpage_sft; slave->mtd.name = parts[i].name; slave->mtd.bank_size = master->bank_size; Loading
drivers/mtd/nand/nand_base.c +44 −9 Original line number Diff line number Diff line Loading @@ -1590,7 +1590,7 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, return NULL; } #define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0 #define NOTALIGNED(x) (x & (chip->subpagesize - 1)) != 0 /** * nand_do_write_ops - [Internal] NAND write with ECC Loading @@ -1603,15 +1603,16 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) { int chipnr, realpage, page, blockmask; int chipnr, realpage, page, blockmask, column; struct nand_chip *chip = mtd->priv; uint32_t writelen = ops->len; uint8_t *oob = ops->oobbuf; uint8_t *buf = ops->datbuf; int bytes = mtd->writesize; int ret; int ret, subpage; ops->retlen = 0; if (!writelen) return 0; /* reject writes, which are not page aligned */ if (NOTALIGNED(to) || NOTALIGNED(ops->len)) { Loading @@ -1620,8 +1621,11 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, return -EINVAL; } if (!writelen) return 0; column = to & (mtd->writesize - 1); subpage = column || (writelen & (mtd->writesize - 1)); if (subpage && oob) return -EINVAL; chipnr = (int)(to >> chip->chip_shift); chip->select_chip(mtd, chipnr); Loading @@ -1644,12 +1648,24 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, memset(chip->oob_poi, 0xff, mtd->oobsize); while(1) { int bytes = mtd->writesize; int cached = writelen > bytes && page != blockmask; uint8_t *wbuf = buf; /* Partial page write ? */ if (unlikely(column || writelen < (mtd->writesize - 1))) { cached = 0; bytes = min_t(int, bytes - column, (int) writelen); chip->pagebuf = -1; memset(chip->buffers->databuf, 0xff, mtd->writesize); memcpy(&chip->buffers->databuf[column], buf, bytes); wbuf = chip->buffers->databuf; } if (unlikely(oob)) oob = nand_fill_oob(chip, oob, ops); ret = chip->write_page(mtd, chip, buf, page, cached, ret = chip->write_page(mtd, chip, wbuf, page, cached, (ops->mode == MTD_OOB_RAW)); if (ret) break; Loading @@ -1658,6 +1674,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, if (!writelen) break; column = 0; buf += bytes; realpage++; Loading Loading @@ -2201,8 +2218,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, /* Newer devices have all the information in additional id bytes */ if (!type->pagesize) { int extid; /* The 3rd id byte contains non relevant data ATM */ extid = chip->read_byte(mtd); /* The 3rd id byte holds MLC / multichip data */ chip->cellinfo = chip->read_byte(mtd); /* The 4th id byte is the important one */ extid = chip->read_byte(mtd); /* Calc pagesize */ Loading Loading @@ -2482,6 +2499,24 @@ int nand_scan_tail(struct mtd_info *mtd) } chip->ecc.total = chip->ecc.steps * chip->ecc.bytes; /* * Allow subpage writes up to ecc.steps. Not possible for MLC * FLASH. */ if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) { switch(chip->ecc.steps) { case 2: mtd->subpage_sft = 1; break; case 4: case 8: mtd->subpage_sft = 2; break; } } chip->subpagesize = mtd->writesize >> mtd->subpage_sft; /* Initialize state */ chip->state = FL_READY; Loading
include/linux/mtd/mtd.h +2 −0 Original line number Diff line number Diff line Loading @@ -200,6 +200,8 @@ struct mtd_info { /* ECC status information */ struct mtd_ecc_stats ecc_stats; /* Subpage shift (NAND) */ int subpage_sft; void *priv; Loading
include/linux/mtd/nand.h +9 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,9 @@ typedef enum { * for all large page devices, as they do not support * autoincrement.*/ #define NAND_NO_READRDY 0x00000100 /* Chip does not allow subpage writes */ #define NAND_NO_SUBPAGE_WRITE 0x00000200 /* Options valid for Samsung large page devices */ #define NAND_SAMSUNG_LP_OPTIONS \ Loading Loading @@ -193,6 +196,9 @@ typedef enum { /* Nand scan has allocated controller struct */ #define NAND_CONTROLLER_ALLOC 0x80000000 /* Cell info constants */ #define NAND_CI_CHIPNR_MSK 0x03 #define NAND_CI_CELLTYPE_MSK 0x0C /* * nand_state_t - chip states Loading Loading @@ -341,6 +347,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 * @subpagesize: [INTERN] holds the subpagesize * @ecclayout: [REPLACEABLE] the default ecc placement scheme * @bbt: [INTERN] bad block table pointer * @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup Loading Loading @@ -388,6 +395,8 @@ struct nand_chip { unsigned long chipsize; int pagemask; int pagebuf; int subpagesize; uint8_t cellinfo; int badblockpos; nand_state_t state; Loading