mtd: spinand: Instantiate a SPI-NAND on-die ECC engine
Make use of the existing functions taken from the SPI-NAND core to instantiate an on-die ECC engine specific to the SPI-NAND core. The next step will be to tweak the core to use this object instead of calling the helpers directly. Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Link: https://lore.kernel.org/linux-mtd/20200930154109.3922-4-miquel.raynal@bootlin.com
This commit is contained in:
parent
55a1a71a7f
commit
945845b54c
|
@ -246,6 +246,73 @@ static const struct mtd_ooblayout_ops spinand_noecc_ooblayout = {
|
|||
.free = spinand_noecc_ooblayout_free,
|
||||
};
|
||||
|
||||
static int spinand_ondie_ecc_init_ctx(struct nand_device *nand)
|
||||
{
|
||||
struct spinand_device *spinand = nand_to_spinand(nand);
|
||||
struct mtd_info *mtd = nanddev_to_mtd(nand);
|
||||
struct spinand_ondie_ecc_conf *engine_conf;
|
||||
|
||||
nand->ecc.ctx.conf.engine_type = NAND_ECC_ENGINE_TYPE_ON_DIE;
|
||||
nand->ecc.ctx.conf.step_size = nand->ecc.requirements.step_size;
|
||||
nand->ecc.ctx.conf.strength = nand->ecc.requirements.strength;
|
||||
|
||||
engine_conf = kzalloc(sizeof(*engine_conf), GFP_KERNEL);
|
||||
if (!engine_conf)
|
||||
return -ENOMEM;
|
||||
|
||||
nand->ecc.ctx.priv = engine_conf;
|
||||
|
||||
if (spinand->eccinfo.ooblayout)
|
||||
mtd_set_ooblayout(mtd, spinand->eccinfo.ooblayout);
|
||||
else
|
||||
mtd_set_ooblayout(mtd, &spinand_noecc_ooblayout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void spinand_ondie_ecc_cleanup_ctx(struct nand_device *nand)
|
||||
{
|
||||
kfree(nand->ecc.ctx.priv);
|
||||
}
|
||||
|
||||
static int spinand_ondie_ecc_prepare_io_req(struct nand_device *nand,
|
||||
struct nand_page_io_req *req)
|
||||
{
|
||||
struct spinand_device *spinand = nand_to_spinand(nand);
|
||||
bool enable = (req->mode != MTD_OPS_RAW);
|
||||
|
||||
/* Only enable or disable the engine */
|
||||
return spinand_ecc_enable(spinand, enable);
|
||||
}
|
||||
|
||||
static int spinand_ondie_ecc_finish_io_req(struct nand_device *nand,
|
||||
struct nand_page_io_req *req)
|
||||
{
|
||||
struct spinand_ondie_ecc_conf *engine_conf = nand->ecc.ctx.priv;
|
||||
struct spinand_device *spinand = nand_to_spinand(nand);
|
||||
|
||||
if (req->mode == MTD_OPS_RAW)
|
||||
return 0;
|
||||
|
||||
/* Nothing to do when finishing a page write */
|
||||
if (req->type == NAND_PAGE_WRITE)
|
||||
return 0;
|
||||
|
||||
/* Finish a page write: check the status, report errors/bitflips */
|
||||
return spinand_check_ecc_status(spinand, engine_conf->status);
|
||||
}
|
||||
|
||||
static struct nand_ecc_engine_ops spinand_ondie_ecc_engine_ops = {
|
||||
.init_ctx = spinand_ondie_ecc_init_ctx,
|
||||
.cleanup_ctx = spinand_ondie_ecc_cleanup_ctx,
|
||||
.prepare_io_req = spinand_ondie_ecc_prepare_io_req,
|
||||
.finish_io_req = spinand_ondie_ecc_finish_io_req,
|
||||
};
|
||||
|
||||
static __maybe_unused struct nand_ecc_engine spinand_ondie_ecc_engine = {
|
||||
.ops = &spinand_ondie_ecc_engine_ops,
|
||||
};
|
||||
|
||||
static int spinand_write_enable_op(struct spinand_device *spinand)
|
||||
{
|
||||
struct spi_mem_op op = SPINAND_WR_EN_DIS_OP(true);
|
||||
|
|
|
@ -286,6 +286,15 @@ struct spinand_ecc_info {
|
|||
#define SPINAND_HAS_QE_BIT BIT(0)
|
||||
#define SPINAND_HAS_CR_FEAT_BIT BIT(1)
|
||||
|
||||
/**
|
||||
* struct spinand_ondie_ecc_conf - private SPI-NAND on-die ECC engine structure
|
||||
* @status: status of the last wait operation that will be used in case
|
||||
* ->get_status() is not populated by the spinand device.
|
||||
*/
|
||||
struct spinand_ondie_ecc_conf {
|
||||
u8 status;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct spinand_info - Structure used to describe SPI NAND chips
|
||||
* @model: model name
|
||||
|
|
Loading…
Reference in New Issue