mtd: spinand: Move ECC related definitions earlier in the driver
Prepare the creation of a SPI-NAND on-die ECC engine by gathering the ECC-related code earlier enough in the core to avoid the need for forward declarations. The next step is to actually create that engine by implementing the generic ECC interface. Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Link: https://lore.kernel.org/linux-mtd/20200930154109.3922-3-miquel.raynal@bootlin.com
This commit is contained in:
parent
93afb10e22
commit
55a1a71a7f
@ -193,6 +193,59 @@ static int spinand_ecc_enable(struct spinand_device *spinand,
|
|||||||
enable ? CFG_ECC_ENABLE : 0);
|
enable ? CFG_ECC_ENABLE : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int spinand_check_ecc_status(struct spinand_device *spinand, u8 status)
|
||||||
|
{
|
||||||
|
struct nand_device *nand = spinand_to_nand(spinand);
|
||||||
|
|
||||||
|
if (spinand->eccinfo.get_status)
|
||||||
|
return spinand->eccinfo.get_status(spinand, status);
|
||||||
|
|
||||||
|
switch (status & STATUS_ECC_MASK) {
|
||||||
|
case STATUS_ECC_NO_BITFLIPS:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case STATUS_ECC_HAS_BITFLIPS:
|
||||||
|
/*
|
||||||
|
* We have no way to know exactly how many bitflips have been
|
||||||
|
* fixed, so let's return the maximum possible value so that
|
||||||
|
* wear-leveling layers move the data immediately.
|
||||||
|
*/
|
||||||
|
return nanddev_get_ecc_conf(nand)->strength;
|
||||||
|
|
||||||
|
case STATUS_ECC_UNCOR_ERROR:
|
||||||
|
return -EBADMSG;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int spinand_noecc_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||||
|
struct mtd_oob_region *region)
|
||||||
|
{
|
||||||
|
return -ERANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int spinand_noecc_ooblayout_free(struct mtd_info *mtd, int section,
|
||||||
|
struct mtd_oob_region *region)
|
||||||
|
{
|
||||||
|
if (section)
|
||||||
|
return -ERANGE;
|
||||||
|
|
||||||
|
/* Reserve 2 bytes for the BBM. */
|
||||||
|
region->offset = 2;
|
||||||
|
region->length = 62;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct mtd_ooblayout_ops spinand_noecc_ooblayout = {
|
||||||
|
.ecc = spinand_noecc_ooblayout_ecc,
|
||||||
|
.free = spinand_noecc_ooblayout_free,
|
||||||
|
};
|
||||||
|
|
||||||
static int spinand_write_enable_op(struct spinand_device *spinand)
|
static int spinand_write_enable_op(struct spinand_device *spinand)
|
||||||
{
|
{
|
||||||
struct spi_mem_op op = SPINAND_WR_EN_DIS_OP(true);
|
struct spi_mem_op op = SPINAND_WR_EN_DIS_OP(true);
|
||||||
@ -402,35 +455,6 @@ static int spinand_lock_block(struct spinand_device *spinand, u8 lock)
|
|||||||
return spinand_write_reg_op(spinand, REG_BLOCK_LOCK, lock);
|
return spinand_write_reg_op(spinand, REG_BLOCK_LOCK, lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int spinand_check_ecc_status(struct spinand_device *spinand, u8 status)
|
|
||||||
{
|
|
||||||
struct nand_device *nand = spinand_to_nand(spinand);
|
|
||||||
|
|
||||||
if (spinand->eccinfo.get_status)
|
|
||||||
return spinand->eccinfo.get_status(spinand, status);
|
|
||||||
|
|
||||||
switch (status & STATUS_ECC_MASK) {
|
|
||||||
case STATUS_ECC_NO_BITFLIPS:
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case STATUS_ECC_HAS_BITFLIPS:
|
|
||||||
/*
|
|
||||||
* We have no way to know exactly how many bitflips have been
|
|
||||||
* fixed, so let's return the maximum possible value so that
|
|
||||||
* wear-leveling layers move the data immediately.
|
|
||||||
*/
|
|
||||||
return nanddev_get_ecc_conf(nand)->strength;
|
|
||||||
|
|
||||||
case STATUS_ECC_UNCOR_ERROR:
|
|
||||||
return -EBADMSG;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int spinand_read_page(struct spinand_device *spinand,
|
static int spinand_read_page(struct spinand_device *spinand,
|
||||||
const struct nand_page_io_req *req,
|
const struct nand_page_io_req *req,
|
||||||
bool ecc_enabled)
|
bool ecc_enabled)
|
||||||
@ -965,30 +989,6 @@ static int spinand_detect(struct spinand_device *spinand)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int spinand_noecc_ooblayout_ecc(struct mtd_info *mtd, int section,
|
|
||||||
struct mtd_oob_region *region)
|
|
||||||
{
|
|
||||||
return -ERANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int spinand_noecc_ooblayout_free(struct mtd_info *mtd, int section,
|
|
||||||
struct mtd_oob_region *region)
|
|
||||||
{
|
|
||||||
if (section)
|
|
||||||
return -ERANGE;
|
|
||||||
|
|
||||||
/* Reserve 2 bytes for the BBM. */
|
|
||||||
region->offset = 2;
|
|
||||||
region->length = 62;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct mtd_ooblayout_ops spinand_noecc_ooblayout = {
|
|
||||||
.ecc = spinand_noecc_ooblayout_ecc,
|
|
||||||
.free = spinand_noecc_ooblayout_free,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int spinand_init(struct spinand_device *spinand)
|
static int spinand_init(struct spinand_device *spinand)
|
||||||
{
|
{
|
||||||
struct device *dev = &spinand->spimem->spi->dev;
|
struct device *dev = &spinand->spimem->spi->dev;
|
||||||
|
Loading…
Reference in New Issue
Block a user