150 lines
3.6 KiB
C
150 lines
3.6 KiB
C
|
|
/*
|
||
|
|
* Copyright (C) 2026 ChuangDian, Xu
|
||
|
|
*
|
||
|
|
* Author: ChuangDian, Xu <xcdanswer@gmail.com>
|
||
|
|
*/
|
||
|
|
|
||
|
|
#ifndef __NAND_H__
|
||
|
|
#define __NAND_H__
|
||
|
|
|
||
|
|
#include "typesdef.h"
|
||
|
|
#include "dev.h"
|
||
|
|
#include "osal/mutex.h"
|
||
|
|
|
||
|
|
|
||
|
|
#define NAND_MAX_CHIPS 5
|
||
|
|
|
||
|
|
#define DEV_REG_CNT (4)
|
||
|
|
|
||
|
|
#define NAND_MAX_BLOCKS 32768 /**< Max number of Blocks */
|
||
|
|
#define NAND_MAX_PAGE_SIZE 2048 /**< Max page size of NAND flash */
|
||
|
|
#define NAND_MAX_OOB_SIZE 64 /**< Max OOB bytes of a NAND flash page */
|
||
|
|
#define NAND_ECC_SIZE 256 /**< ECC block size */
|
||
|
|
#define NAND_ECC_BYTES 2 /**< ECC bytes per ECC block */
|
||
|
|
|
||
|
|
|
||
|
|
#define NAND_ERASE_FAIL 0x01
|
||
|
|
#define NAND_PROGRAM_FAIL 0x02
|
||
|
|
#define NAND_ECC_ERROR 0X04
|
||
|
|
|
||
|
|
struct NandOobFree {
|
||
|
|
uint32_t Offset;
|
||
|
|
uint32_t Length;
|
||
|
|
};
|
||
|
|
|
||
|
|
/*
|
||
|
|
* ECC layout control structure. Exported to user space for
|
||
|
|
* diagnosis and to allow creation of raw images
|
||
|
|
*/
|
||
|
|
struct NandEccLayout {
|
||
|
|
uint32_t EccBytes;
|
||
|
|
uint32_t EccPos;
|
||
|
|
uint32_t OobAvail;
|
||
|
|
struct NandOobFree OobFree;
|
||
|
|
};
|
||
|
|
|
||
|
|
/*
|
||
|
|
* This enum contains ECC Mode
|
||
|
|
*/
|
||
|
|
typedef enum {
|
||
|
|
NAND_ECC_NONE,
|
||
|
|
NAND_ECC_SOFT_BCH,
|
||
|
|
NAND_ECC_ONDIE /**< On-Die ECC */
|
||
|
|
} Nand_EccMode;
|
||
|
|
|
||
|
|
struct NandEccCtrl {
|
||
|
|
Nand_EccMode Mode;
|
||
|
|
uint32_t EccSteps; /**< Number of ECC steps for the flash page */
|
||
|
|
uint32_t EccSize; /**< ECC size */
|
||
|
|
uint32_t EccBytes; /**< Number of ECC bytes for a block */
|
||
|
|
uint32_t EccTotalBytes; /**< Total number of ECC bytes for Page */
|
||
|
|
uint32_t Strength;
|
||
|
|
struct NandEccLayout *Layout;
|
||
|
|
void *Priv;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct NandBuffers {
|
||
|
|
uint8_t DataBuf[NAND_MAX_PAGE_SIZE];
|
||
|
|
uint8_t EccCode[NAND_MAX_OOB_SIZE]; /**< Buffer for stored ECC */
|
||
|
|
uint8_t EccCalc[NAND_MAX_OOB_SIZE]; /**< Buffer for calculated ECC */
|
||
|
|
uint32_t Rcache;
|
||
|
|
};
|
||
|
|
|
||
|
|
enum nand_ctl_cmd {
|
||
|
|
NAND_OP_RD_SET,
|
||
|
|
NAND_OP_WR_SET,
|
||
|
|
NAND_FREQ_SET,
|
||
|
|
NAND_IS_BAD_BLOCK,
|
||
|
|
NAND_READ_OOB,
|
||
|
|
NAND_WRITE_OOB,
|
||
|
|
NAND_ECC_STATUS,
|
||
|
|
NAND_STATUS,
|
||
|
|
NAND_N_OF_BLKS,
|
||
|
|
NAND_PG2PG_PAGE,
|
||
|
|
};
|
||
|
|
|
||
|
|
enum nand_req_type {
|
||
|
|
NAND_READ_PAGE_REQ,
|
||
|
|
NAND_READ_PAGE_COL_REQ,
|
||
|
|
NAND_WRITE_PAGE_REQ,
|
||
|
|
NAND_ERASE_REQ,
|
||
|
|
NAND_PG2PG_REQ,
|
||
|
|
NAND_STATUS_REQ,
|
||
|
|
};
|
||
|
|
|
||
|
|
struct nand_req {
|
||
|
|
uint32 type;
|
||
|
|
union {
|
||
|
|
struct _pc {
|
||
|
|
uint32 page;
|
||
|
|
uint32 col;
|
||
|
|
} pc;
|
||
|
|
struct _p2p {
|
||
|
|
uint32 src;
|
||
|
|
uint32 dst;
|
||
|
|
} p2p;
|
||
|
|
uint32 page;
|
||
|
|
uint32 blk;
|
||
|
|
uint32 ret;
|
||
|
|
};
|
||
|
|
uint8 *buf;
|
||
|
|
uint32 len;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct nand_dev;
|
||
|
|
struct nand_ops {
|
||
|
|
int (*init)(struct nand_dev *nd);
|
||
|
|
int (*rdpg)(struct nand_dev *nd, uint32 page, uint8 *buf, uint32 len);
|
||
|
|
int (*wrpg)(struct nand_dev *nd, uint32 page, uint8 *buf, uint32 len);
|
||
|
|
int (*erase)(struct nand_dev *nd, uint32 blk);
|
||
|
|
int (*ctl)(struct nand_dev *nd, uint32 cmd, uint32 param1, uint32 param2);
|
||
|
|
};
|
||
|
|
|
||
|
|
struct nand_dev {
|
||
|
|
struct dev_obj dev;
|
||
|
|
struct spi_nand *sn;
|
||
|
|
struct nand_ops *ops;
|
||
|
|
uint8_t *bbt;
|
||
|
|
uint32_t rd_ofs;
|
||
|
|
uint32_t status;
|
||
|
|
int (*pg_rd)(struct nand_dev *nd, uint32 page, uint8 *buf, uint32 len);
|
||
|
|
int (*pg_wr)(struct nand_dev *nd, uint32 page, uint8 *buf, uint32 len);
|
||
|
|
struct os_mutex mutex;
|
||
|
|
uint32_t \
|
||
|
|
ofs_shift_block : 8,
|
||
|
|
ofs_shift_page : 8,
|
||
|
|
ofs_shift_oob : 8,
|
||
|
|
page_shift_block: 8;
|
||
|
|
struct NandEccCtrl EccCtrl; /**< ECC configuration parameters */
|
||
|
|
struct NandBuffers *Buffers;
|
||
|
|
};
|
||
|
|
|
||
|
|
int nand_init(struct nand_dev *nand);
|
||
|
|
int nand_req(struct nand_dev *nd, struct nand_req *req);
|
||
|
|
|
||
|
|
uint8_t bbt_is_bad(struct nand_dev *nand, int block);
|
||
|
|
|
||
|
|
void bbt_mark_entry(struct nand_dev *nand, int block);
|
||
|
|
int nand_dev_register(uint16 dev_id, struct nand_dev *nand);
|
||
|
|
#endif
|