Commit 1e3b37aa authored by Miquel Raynal's avatar Miquel Raynal
Browse files

mtd: rawnand: Use the ECC framework OOB layouts

parent c441bcd3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -980,7 +980,7 @@ static int anfc_init_hw_ecc_controller(struct arasan_nfc *nfc,
		return -EINVAL;
	}

	mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
	mtd_set_ooblayout(mtd, nand_get_large_page_ooblayout());

	ecc->steps = mtd->writesize / ecc->size;
	ecc->algo = NAND_ECC_ALGO_BCH;
+1 −1
Original line number Diff line number Diff line
@@ -1108,7 +1108,7 @@ static int atmel_nand_pmecc_init(struct nand_chip *chip)

	chip->options |= NAND_NO_SUBPAGE_WRITE;

	mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
	mtd_set_ooblayout(mtd, nand_get_large_page_ooblayout());

	return 0;
}
+2 −1
Original line number Diff line number Diff line
@@ -645,7 +645,8 @@ static int davinci_nand_attach_chip(struct nand_chip *chip)
				mtd_set_ooblayout(mtd,
						  &hwecc4_small_ooblayout_ops);
			} else if (chunks == 4 || chunks == 8) {
				mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
				mtd_set_ooblayout(mtd,
						  nand_get_large_page_ooblayout());
				info->chip.ecc.read_page = nand_davinci_read_page_hwecc_oob_first;
			} else {
				return -EIO;
+3 −3
Original line number Diff line number Diff line
@@ -243,8 +243,10 @@ static int ingenic_nand_attach_chip(struct nand_chip *chip)
	/* For legacy reasons we use a different layout on the qi,lb60 board. */
	if (of_machine_is_compatible("qi,lb60"))
		mtd_set_ooblayout(mtd, &qi_lb60_ooblayout_ops);
	else
	else if (nfc->soc_info->oob_layout)
		mtd_set_ooblayout(mtd, nfc->soc_info->oob_layout);
	else
		mtd_set_ooblayout(mtd, nand_get_large_page_ooblayout());

	return 0;
}
@@ -532,7 +534,6 @@ static const struct jz_soc_info jz4740_soc_info = {
	.data_offset = 0x00000000,
	.cmd_offset = 0x00008000,
	.addr_offset = 0x00010000,
	.oob_layout = &nand_ooblayout_lp_ops,
};

static const struct jz_soc_info jz4725b_soc_info = {
@@ -546,7 +547,6 @@ static const struct jz_soc_info jz4780_soc_info = {
	.data_offset = 0x00000000,
	.cmd_offset = 0x00400000,
	.addr_offset = 0x00800000,
	.oob_layout = &nand_ooblayout_lp_ops,
};

static const struct of_device_id ingenic_nand_dt_match[] = {
+9 −165
Original line number Diff line number Diff line
@@ -46,166 +46,6 @@

#include "internals.h"

/* Define default oob placement schemes for large and small page devices */
static int nand_ooblayout_ecc_sp(struct mtd_info *mtd, int section,
				 struct mtd_oob_region *oobregion)
{
	struct nand_chip *chip = mtd_to_nand(mtd);
	struct nand_ecc_ctrl *ecc = &chip->ecc;

	if (section > 1)
		return -ERANGE;

	if (!section) {
		oobregion->offset = 0;
		if (mtd->oobsize == 16)
			oobregion->length = 4;
		else
			oobregion->length = 3;
	} else {
		if (mtd->oobsize == 8)
			return -ERANGE;

		oobregion->offset = 6;
		oobregion->length = ecc->total - 4;
	}

	return 0;
}

static int nand_ooblayout_free_sp(struct mtd_info *mtd, int section,
				  struct mtd_oob_region *oobregion)
{
	if (section > 1)
		return -ERANGE;

	if (mtd->oobsize == 16) {
		if (section)
			return -ERANGE;

		oobregion->length = 8;
		oobregion->offset = 8;
	} else {
		oobregion->length = 2;
		if (!section)
			oobregion->offset = 3;
		else
			oobregion->offset = 6;
	}

	return 0;
}

const struct mtd_ooblayout_ops nand_ooblayout_sp_ops = {
	.ecc = nand_ooblayout_ecc_sp,
	.free = nand_ooblayout_free_sp,
};
EXPORT_SYMBOL_GPL(nand_ooblayout_sp_ops);

static int nand_ooblayout_ecc_lp(struct mtd_info *mtd, int section,
				 struct mtd_oob_region *oobregion)
{
	struct nand_chip *chip = mtd_to_nand(mtd);
	struct nand_ecc_ctrl *ecc = &chip->ecc;

	if (section || !ecc->total)
		return -ERANGE;

	oobregion->length = ecc->total;
	oobregion->offset = mtd->oobsize - oobregion->length;

	return 0;
}

static int nand_ooblayout_free_lp(struct mtd_info *mtd, int section,
				  struct mtd_oob_region *oobregion)
{
	struct nand_chip *chip = mtd_to_nand(mtd);
	struct nand_ecc_ctrl *ecc = &chip->ecc;

	if (section)
		return -ERANGE;

	oobregion->length = mtd->oobsize - ecc->total - 2;
	oobregion->offset = 2;

	return 0;
}

const struct mtd_ooblayout_ops nand_ooblayout_lp_ops = {
	.ecc = nand_ooblayout_ecc_lp,
	.free = nand_ooblayout_free_lp,
};
EXPORT_SYMBOL_GPL(nand_ooblayout_lp_ops);

/*
 * Support the old "large page" layout used for 1-bit Hamming ECC where ECC
 * are placed at a fixed offset.
 */
static int nand_ooblayout_ecc_lp_hamming(struct mtd_info *mtd, int section,
					 struct mtd_oob_region *oobregion)
{
	struct nand_chip *chip = mtd_to_nand(mtd);
	struct nand_ecc_ctrl *ecc = &chip->ecc;

	if (section)
		return -ERANGE;

	switch (mtd->oobsize) {
	case 64:
		oobregion->offset = 40;
		break;
	case 128:
		oobregion->offset = 80;
		break;
	default:
		return -EINVAL;
	}

	oobregion->length = ecc->total;
	if (oobregion->offset + oobregion->length > mtd->oobsize)
		return -ERANGE;

	return 0;
}

static int nand_ooblayout_free_lp_hamming(struct mtd_info *mtd, int section,
					  struct mtd_oob_region *oobregion)
{
	struct nand_chip *chip = mtd_to_nand(mtd);
	struct nand_ecc_ctrl *ecc = &chip->ecc;
	int ecc_offset = 0;

	if (section < 0 || section > 1)
		return -ERANGE;

	switch (mtd->oobsize) {
	case 64:
		ecc_offset = 40;
		break;
	case 128:
		ecc_offset = 80;
		break;
	default:
		return -EINVAL;
	}

	if (section == 0) {
		oobregion->offset = 2;
		oobregion->length = ecc_offset - 2;
	} else {
		oobregion->offset = ecc_offset + ecc->total;
		oobregion->length = mtd->oobsize - oobregion->offset;
	}

	return 0;
}

static const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = {
	.ecc = nand_ooblayout_ecc_lp_hamming,
	.free = nand_ooblayout_free_lp_hamming,
};

static int nand_pairing_dist3_get_info(struct mtd_info *mtd, int page,
				       struct mtd_pairing_info *info)
{
@@ -5372,7 +5212,7 @@ static int nand_set_ecc_soft_ops(struct nand_chip *chip)
				return -EINVAL;
			}

			mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
			mtd_set_ooblayout(mtd, nand_get_large_page_ooblayout());

		}

@@ -5381,7 +5221,7 @@ static int nand_set_ecc_soft_ops(struct nand_chip *chip)
		 * used, otherwise we don't know how many bytes can really be
		 * used.
		 */
		if (mtd->ooblayout == &nand_ooblayout_lp_ops &&
		if (mtd->ooblayout == nand_get_large_page_ooblayout() &&
		    ecc->options & NAND_ECC_MAXIMIZE) {
			int steps, bytes;

@@ -5783,11 +5623,12 @@ static int nand_scan_tail(struct nand_chip *chip)
		switch (mtd->oobsize) {
		case 8:
		case 16:
			mtd_set_ooblayout(mtd, &nand_ooblayout_sp_ops);
			mtd_set_ooblayout(mtd, nand_get_small_page_ooblayout());
			break;
		case 64:
		case 128:
			mtd_set_ooblayout(mtd, &nand_ooblayout_lp_hamming_ops);
			mtd_set_ooblayout(mtd,
					  nand_get_large_page_hamming_ooblayout());
			break;
		default:
			/*
@@ -5799,7 +5640,7 @@ static int nand_scan_tail(struct nand_chip *chip)
			 */
			if (ecc->engine_type == NAND_ECC_ENGINE_TYPE_NONE) {
				mtd_set_ooblayout(mtd,
						&nand_ooblayout_lp_ops);
						  nand_get_large_page_ooblayout());
				break;
			}

@@ -5954,7 +5795,10 @@ static int nand_scan_tail(struct nand_chip *chip)
		ret = -EINVAL;
		goto err_nand_manuf_cleanup;
	}

	ecc->total = ecc->steps * ecc->bytes;
	chip->base.ecc.ctx.total = ecc->total;

	if (ecc->total > mtd->oobsize) {
		WARN(1, "Total number of ECC bytes exceeded oobsize\n");
		ret = -EINVAL;
Loading