mtd: add mtd_ooblayout_xxx() helper functions

In order to make the ecclayout definition completely dynamic we need to
rework the way the OOB layout are defined and iterated.

Create a few mtd_ooblayout_xxx() helpers to ease OOB bytes manipulation
and hide ecclayout internals to their users.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
[Linux commit: 75eb2cec251fda33c9bb716ecc372819abb9278a]
[masahiro:
 cherry-pick more code from adbbc3bc827eb1f43a932d783f09ba55c8ec8379]
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
This commit is contained in:
Boris Brezillon 2017-11-22 02:38:23 +09:00 committed by Masahiro Yamada
parent 1fb87de83d
commit 13f3b04f61
2 changed files with 417 additions and 0 deletions

View file

@ -103,6 +103,36 @@ struct mtd_oob_ops {
#else
#define MTD_MAX_ECCPOS_ENTRIES_LARGE 680
#endif
/**
* struct mtd_oob_region - oob region definition
* @offset: region offset
* @length: region length
*
* This structure describes a region of the OOB area, and is used
* to retrieve ECC or free bytes sections.
* Each section is defined by an offset within the OOB area and a
* length.
*/
struct mtd_oob_region {
u32 offset;
u32 length;
};
/*
* struct mtd_ooblayout_ops - NAND OOB layout operations
* @ecc: function returning an ECC region in the OOB area.
* Should return -ERANGE if %section exceeds the total number of
* ECC sections.
* @free: function returning a free region in the OOB area.
* Should return -ERANGE if %section exceeds the total number of
* free sections.
*/
struct mtd_ooblayout_ops {
int (*ecc)(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobecc);
int (*free)(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobfree);
};
/*
* Internal ECC layout control structure. For historical reasons, there is a
@ -179,6 +209,9 @@ struct mtd_info {
#endif
int index;
/* OOB layout description */
const struct mtd_ooblayout_ops *ooblayout;
/* ECC layout structure pointer - read only! */
struct nand_ecclayout *ecclayout;
@ -278,6 +311,30 @@ struct mtd_info {
int usecount;
};
int mtd_ooblayout_ecc(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobecc);
int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte,
int *section,
struct mtd_oob_region *oobregion);
int mtd_ooblayout_get_eccbytes(struct mtd_info *mtd, u8 *eccbuf,
const u8 *oobbuf, int start, int nbytes);
int mtd_ooblayout_set_eccbytes(struct mtd_info *mtd, const u8 *eccbuf,
u8 *oobbuf, int start, int nbytes);
int mtd_ooblayout_free(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobfree);
int mtd_ooblayout_get_databytes(struct mtd_info *mtd, u8 *databuf,
const u8 *oobbuf, int start, int nbytes);
int mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf,
u8 *oobbuf, int start, int nbytes);
int mtd_ooblayout_count_freebytes(struct mtd_info *mtd);
int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd);
static inline void mtd_set_ooblayout(struct mtd_info *mtd,
const struct mtd_ooblayout_ops *ooblayout)
{
mtd->ooblayout = ooblayout;
}
static inline int mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
{
return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;