mtd: nand: qcom: switch to mtd_ooblayout_ops
Implementing the mtd_ooblayout_ops interface is the new way of exposing ECC/OOB layout to MTD users. Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> Tested-by: Archit Taneja <architt@codeaurora.org>
This commit is contained in:
parent
3cf32d1802
commit
421e81c4c6
|
@ -1707,61 +1707,52 @@ static void qcom_nandc_select_chip(struct mtd_info *mtd, int chipnr)
|
||||||
* This layout is read as is when ECC is disabled. When ECC is enabled, the
|
* This layout is read as is when ECC is disabled. When ECC is enabled, the
|
||||||
* inaccessible Bad Block byte(s) are ignored when we write to a page/oob,
|
* inaccessible Bad Block byte(s) are ignored when we write to a page/oob,
|
||||||
* and assumed as 0xffs when we read a page/oob. The ECC, unused and
|
* and assumed as 0xffs when we read a page/oob. The ECC, unused and
|
||||||
* dummy/real bad block bytes are grouped as ecc bytes in nand_ecclayout (i.e,
|
* dummy/real bad block bytes are grouped as ecc bytes (i.e, ecc->bytes is
|
||||||
* ecc->bytes is the sum of the three).
|
* the sum of the three).
|
||||||
*/
|
*/
|
||||||
|
static int qcom_nand_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||||
static struct nand_ecclayout *
|
struct mtd_oob_region *oobregion)
|
||||||
qcom_nand_create_layout(struct qcom_nand_host *host)
|
|
||||||
{
|
{
|
||||||
struct nand_chip *chip = &host->chip;
|
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||||
struct mtd_info *mtd = nand_to_mtd(chip);
|
struct qcom_nand_host *host = to_qcom_nand_host(chip);
|
||||||
struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
|
|
||||||
struct nand_ecc_ctrl *ecc = &chip->ecc;
|
struct nand_ecc_ctrl *ecc = &chip->ecc;
|
||||||
struct nand_ecclayout *layout;
|
|
||||||
int i, j, steps, pos = 0, shift = 0;
|
|
||||||
|
|
||||||
layout = devm_kzalloc(nandc->dev, sizeof(*layout), GFP_KERNEL);
|
if (section > 1)
|
||||||
if (!layout)
|
return -ERANGE;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
steps = mtd->writesize / ecc->size;
|
if (!section) {
|
||||||
layout->eccbytes = steps * ecc->bytes;
|
oobregion->length = (ecc->bytes * (ecc->steps - 1)) +
|
||||||
|
host->bbm_size;
|
||||||
layout->oobfree[0].offset = (steps - 1) * ecc->bytes + host->bbm_size;
|
oobregion->offset = 0;
|
||||||
layout->oobfree[0].length = steps << 2;
|
} else {
|
||||||
|
oobregion->length = host->ecc_bytes_hw + host->spare_bytes;
|
||||||
/*
|
oobregion->offset = mtd->oobsize - oobregion->length;
|
||||||
* the oob bytes in the first n - 1 codewords are all grouped together
|
|
||||||
* in the format:
|
|
||||||
* DUMMY_BBM + UNUSED + ECC
|
|
||||||
*/
|
|
||||||
for (i = 0; i < steps - 1; i++) {
|
|
||||||
for (j = 0; j < ecc->bytes; j++)
|
|
||||||
layout->eccpos[pos++] = i * ecc->bytes + j;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
return 0;
|
||||||
* the oob bytes in the last codeword are grouped in the format:
|
|
||||||
* BBM + FREE OOB + UNUSED + ECC
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* fill up the bbm positions */
|
|
||||||
for (j = 0; j < host->bbm_size; j++)
|
|
||||||
layout->eccpos[pos++] = i * ecc->bytes + j;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* fill up the ecc and reserved positions, their indices are offseted
|
|
||||||
* by the free oob region
|
|
||||||
*/
|
|
||||||
shift = layout->oobfree[0].length + host->bbm_size;
|
|
||||||
|
|
||||||
for (j = 0; j < (host->ecc_bytes_hw + host->spare_bytes); j++)
|
|
||||||
layout->eccpos[pos++] = i * ecc->bytes + shift + j;
|
|
||||||
|
|
||||||
return layout;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qcom_nand_ooblayout_free(struct mtd_info *mtd, int section,
|
||||||
|
struct mtd_oob_region *oobregion)
|
||||||
|
{
|
||||||
|
struct nand_chip *chip = mtd_to_nand(mtd);
|
||||||
|
struct qcom_nand_host *host = to_qcom_nand_host(chip);
|
||||||
|
struct nand_ecc_ctrl *ecc = &chip->ecc;
|
||||||
|
|
||||||
|
if (section)
|
||||||
|
return -ERANGE;
|
||||||
|
|
||||||
|
oobregion->length = ecc->steps * 4;
|
||||||
|
oobregion->offset = ((ecc->steps - 1) * ecc->bytes) + host->bbm_size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct mtd_ooblayout_ops qcom_nand_ooblayout_ops = {
|
||||||
|
.ecc = qcom_nand_ooblayout_ecc,
|
||||||
|
.free = qcom_nand_ooblayout_free,
|
||||||
|
};
|
||||||
|
|
||||||
static int qcom_nand_host_setup(struct qcom_nand_host *host)
|
static int qcom_nand_host_setup(struct qcom_nand_host *host)
|
||||||
{
|
{
|
||||||
struct nand_chip *chip = &host->chip;
|
struct nand_chip *chip = &host->chip;
|
||||||
|
@ -1848,9 +1839,7 @@ static int qcom_nand_host_setup(struct qcom_nand_host *host)
|
||||||
|
|
||||||
ecc->mode = NAND_ECC_HW;
|
ecc->mode = NAND_ECC_HW;
|
||||||
|
|
||||||
ecc->layout = qcom_nand_create_layout(host);
|
mtd_set_ooblayout(mtd, &qcom_nand_ooblayout_ops);
|
||||||
if (!ecc->layout)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
cwperpage = mtd->writesize / ecc->size;
|
cwperpage = mtd->writesize / ecc->size;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue