mtd: rawnand: Define the "distance 3" MLC pairing scheme

Define a new page pairing scheme for MLC NANDs with a distance of 3
pages between the lower and upper page.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20200503155341.16712-3-miquel.raynal@bootlin.com
This commit is contained in:
Boris Brezillon 2020-05-03 17:53:35 +02:00 committed by Miquel Raynal
parent 5338ef99c9
commit 18729b1776
2 changed files with 53 additions and 0 deletions

View File

@ -75,6 +75,9 @@ extern const struct nand_manufacturer_ops micron_nand_manuf_ops;
extern const struct nand_manufacturer_ops samsung_nand_manuf_ops;
extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops;
/* MLC pairing schemes */
extern const struct mtd_pairing_scheme dist3_pairing_scheme;
/* Core functions */
const struct nand_manufacturer *nand_get_manufacturer(u8 id);
int nand_bbm_get_next_page(struct nand_chip *chip, int page);

View File

@ -205,6 +205,56 @@ static const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = {
.free = nand_ooblayout_free_lp_hamming,
};
static int nand_pairing_dist3_get_info(struct mtd_info *mtd, int page,
struct mtd_pairing_info *info)
{
int lastpage = (mtd->erasesize / mtd->writesize) - 1;
int dist = 3;
if (page == lastpage)
dist = 2;
if (!page || (page & 1)) {
info->group = 0;
info->pair = (page + 1) / 2;
} else {
info->group = 1;
info->pair = (page + 1 - dist) / 2;
}
return 0;
}
static int nand_pairing_dist3_get_wunit(struct mtd_info *mtd,
const struct mtd_pairing_info *info)
{
int lastpair = ((mtd->erasesize / mtd->writesize) - 1) / 2;
int page = info->pair * 2;
int dist = 3;
if (!info->group && !info->pair)
return 0;
if (info->pair == lastpair && info->group)
dist = 2;
if (!info->group)
page--;
else if (info->pair)
page += dist - 1;
if (page >= mtd->erasesize / mtd->writesize)
return -EINVAL;
return page;
}
const struct mtd_pairing_scheme dist3_pairing_scheme = {
.ngroups = 2,
.get_info = nand_pairing_dist3_get_info,
.get_wunit = nand_pairing_dist3_get_wunit,
};
static int check_offs_len(struct nand_chip *chip, loff_t ofs, uint64_t len)
{
int ret = 0;