2023-08-30 16:21:18 +08:00
|
|
|
/*
|
2025-04-23 17:54:31 +08:00
|
|
|
* Copyright (c) 2023-2025, ArtInChip Technology Co., Ltd
|
2023-08-30 16:21:18 +08:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
*
|
|
|
|
|
* Authors: xuan.wen <xuan.wen@artinchip.com>
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef __SPINAND_H__
|
|
|
|
|
#define __SPINAND_H__
|
|
|
|
|
|
|
|
|
|
#include <aic_core.h>
|
|
|
|
|
|
|
|
|
|
#define SPINAND_SUCCESS 0 /**< success */
|
|
|
|
|
#define SPINAND_ERR 1 /**< not found or not supported */
|
|
|
|
|
#define SPINAND_ERR_TIMEOUT 2 /**< timeout error */
|
|
|
|
|
#define SPINAND_ERR_ECC 3 /**< ecc check error */
|
2024-06-04 19:00:30 +08:00
|
|
|
#define SPINAND_TRUE 1
|
|
|
|
|
#define SPINAND_FALSE 0
|
2023-08-30 16:21:18 +08:00
|
|
|
|
|
|
|
|
#define SPINAND_DIE_ID0 (0)
|
|
|
|
|
#define SPINAND_DIE_ID1 (1)
|
|
|
|
|
|
2023-11-09 20:19:51 +08:00
|
|
|
#undef pr_debug
|
|
|
|
|
#ifdef AIC_SPINAND_DRV_DEBUG
|
2023-12-22 10:19:53 +08:00
|
|
|
#define pr_debug pr_info
|
2023-11-09 20:19:51 +08:00
|
|
|
#else
|
|
|
|
|
#define pr_debug(fmt, ...)
|
|
|
|
|
#endif
|
|
|
|
|
|
2023-08-30 16:21:18 +08:00
|
|
|
/**
|
|
|
|
|
* struct nand_bbt - bad block table object
|
|
|
|
|
* @cache: in memory BBT cache
|
|
|
|
|
*/
|
|
|
|
|
struct nand_bbt {
|
|
|
|
|
u8 *cache;
|
|
|
|
|
};
|
|
|
|
|
|
2023-12-22 10:19:53 +08:00
|
|
|
struct aic_spinand;
|
|
|
|
|
|
2024-09-30 17:06:01 +08:00
|
|
|
/*
|
|
|
|
|
* struct spinand_devid - SPI NAND device id structure
|
|
|
|
|
* @id: device id of current chip
|
|
|
|
|
* @len: number of bytes in device id
|
|
|
|
|
*/
|
|
|
|
|
struct spinand_devid {
|
|
|
|
|
const u8 *id;
|
|
|
|
|
const u8 len;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define DEVID(...) \
|
|
|
|
|
{ \
|
|
|
|
|
.id = (const u8[]){ __VA_ARGS__ }, \
|
|
|
|
|
.len = sizeof((u8[]){ __VA_ARGS__ }), \
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-08 19:12:06 +08:00
|
|
|
struct aic_oob_region {
|
|
|
|
|
u32 offset;
|
|
|
|
|
u32 length;
|
|
|
|
|
};
|
|
|
|
|
|
2023-08-30 16:21:18 +08:00
|
|
|
/* SPI NAND flash information */
|
|
|
|
|
struct aic_spinand_info {
|
2024-09-30 17:06:01 +08:00
|
|
|
struct spinand_devid devid;
|
2023-08-30 16:21:18 +08:00
|
|
|
u16 page_size;
|
|
|
|
|
u16 oob_size;
|
2024-01-27 08:47:24 +08:00
|
|
|
u16 block_per_lun;
|
|
|
|
|
u16 pages_per_eraseblock;
|
|
|
|
|
u8 planes_per_lun;
|
2023-08-30 16:21:18 +08:00
|
|
|
u8 is_die_select;
|
|
|
|
|
const char *sz_description;
|
|
|
|
|
struct spi_nand_cmd_cfg *cmd;
|
2023-12-22 10:19:53 +08:00
|
|
|
int (*get_status)(struct aic_spinand *flash, u8 status);
|
2025-01-08 19:12:06 +08:00
|
|
|
int (*oob_get_user)(struct aic_spinand *flash, int section,
|
|
|
|
|
struct aic_oob_region *oobuser);
|
2023-08-30 16:21:18 +08:00
|
|
|
};
|
|
|
|
|
typedef struct aic_spinand_info *aic_spinand_info_t;
|
|
|
|
|
|
2024-01-27 08:47:24 +08:00
|
|
|
#define PAGESIZE(x) (u16)(x)
|
|
|
|
|
#define OOBSIZE(x) (u16)(x)
|
|
|
|
|
#define BPL(x) (u16)(x)
|
|
|
|
|
#define PPB(x) (u16)(x)
|
|
|
|
|
#define PLANENUM(x) (u8)(x)
|
|
|
|
|
#define DIE(x) (u16)(x)
|
|
|
|
|
|
2023-08-30 16:21:18 +08:00
|
|
|
#define SPINAND_MAX_ID_LEN 4
|
|
|
|
|
|
|
|
|
|
struct spinand_id {
|
|
|
|
|
u8 data[SPINAND_MAX_ID_LEN];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct aic_spinand {
|
|
|
|
|
const struct aic_spinand_info *info;
|
|
|
|
|
struct spinand_id id;
|
|
|
|
|
void *user_data;
|
|
|
|
|
void *lock;
|
2025-01-08 19:12:06 +08:00
|
|
|
u8 bus;
|
2023-08-30 16:21:18 +08:00
|
|
|
u8 use_continuous_read;
|
|
|
|
|
u8 qspi_dl_width;
|
|
|
|
|
u8 IsInited;
|
|
|
|
|
u8 *databuf;
|
|
|
|
|
u8 *oobbuf;
|
|
|
|
|
struct nand_bbt bbt;
|
|
|
|
|
};
|
|
|
|
|
typedef struct aic_spinand *aic_spinand_t;
|
|
|
|
|
|
|
|
|
|
int spinand_read_id_op(struct aic_spinand *flash, u8 *id);
|
|
|
|
|
int spinand_block_erase(struct aic_spinand *flash, u16 blk);
|
|
|
|
|
int spinand_flash_init(struct aic_spinand *flash);
|
|
|
|
|
int spinand_read_page(struct aic_spinand *flash, u32 page, u8 *data,
|
|
|
|
|
u32 data_len, u8 *spare, u32 spare_len);
|
|
|
|
|
int spinand_block_isbad(struct aic_spinand *flash, u16 blk);
|
2024-09-03 11:16:08 +08:00
|
|
|
int spinand_get_status(struct aic_spinand *flash, u16 blk);
|
2025-04-23 17:54:31 +08:00
|
|
|
int spinand_set_status(struct aic_spinand *flash, u16 blk, u16 status);
|
2023-08-30 16:21:18 +08:00
|
|
|
int spinand_continuous_read(struct aic_spinand *flash, u32 page, u8 *data,
|
|
|
|
|
u32 size);
|
|
|
|
|
int spinand_write_page(struct aic_spinand *flash, u32 page, const u8 *data,
|
|
|
|
|
u32 data_len, const u8 *spare, u32 spare_len);
|
|
|
|
|
int spinand_block_markbad(struct aic_spinand *flash, u16 blk);
|
|
|
|
|
int spinand_config_set(struct aic_spinand *flash, u8 mask, u8 val);
|
|
|
|
|
int spinand_erase(struct aic_spinand *flash, u32 offset, u32 size);
|
|
|
|
|
int spinand_read(struct aic_spinand *flash, u8 *addr, u32 offset, u32 size);
|
|
|
|
|
int spinand_write(struct aic_spinand *flash, u8 *addr, u32 offset, u32 size);
|
2025-04-23 17:54:31 +08:00
|
|
|
int spinand_get_feature(struct aic_spinand *flash, u8 reg_addr);
|
2023-08-30 16:21:18 +08:00
|
|
|
|
|
|
|
|
#ifdef AIC_SPINAND_CONT_READ
|
|
|
|
|
|
|
|
|
|
#define SPINAND_CMD_READ_FROM_CACHE_X4_CONT_CFG \
|
|
|
|
|
{ \
|
|
|
|
|
SPINAND_CMD_READ_FROM_CACHE_X4, 1, 0, 0, 4, 4 \
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Standard SPI-NAND flash commands
|
|
|
|
|
*/
|
|
|
|
|
#define SPINAND_CMD_RESET 0xff
|
|
|
|
|
#define SPINAND_CMD_GET_FEATURE 0x0f
|
|
|
|
|
#define SPINAND_CMD_SET_FEATURE 0x1f
|
|
|
|
|
#define SPINAND_CMD_PAGE_READ 0x13
|
|
|
|
|
#define SPINAND_CMD_READ_PAGE_CACHE_RDM 0x30
|
|
|
|
|
#define SPINAND_CMD_READ_PAGE_CACHE_LAST 0x3f
|
|
|
|
|
#define SPINAND_CMD_READ_FROM_CACHE 0x03
|
|
|
|
|
#define SPINAND_CMD_READ_FROM_CACHE_FAST 0x0b
|
|
|
|
|
#define SPINAND_CMD_READ_FROM_CACHE_X2 0x3b
|
|
|
|
|
#define SPINAND_CMD_READ_FROM_CACHE_DUAL_IO 0xbb
|
|
|
|
|
#define SPINAND_CMD_READ_FROM_CACHE_X4 0x6b
|
|
|
|
|
#define SPINAND_CMD_READ_FROM_CACHE_QUAD_IO 0xeb
|
|
|
|
|
#define SPINAND_CMD_BLK_ERASE 0xd8
|
|
|
|
|
#define SPINAND_CMD_PROG_EXC 0x10
|
|
|
|
|
#define SPINAND_CMD_PROG_LOAD 0x02
|
|
|
|
|
#define SPINAND_CMD_PROG_LOAD_RDM_DATA 0x84
|
|
|
|
|
#define SPINAND_CMD_PROG_LOAD_X4 0x32
|
|
|
|
|
#define SPINAND_CMD_PROG_LOAD_RDM_DATA_X4 0x34
|
|
|
|
|
#define SPINAND_CMD_READ_ID 0x9f
|
|
|
|
|
#define SPINAND_CMD_WR_DISABLE 0x04
|
|
|
|
|
#define SPINAND_CMD_WR_ENABLE 0x06
|
|
|
|
|
#define SPINAND_CMD_END 0x0
|
|
|
|
|
|
|
|
|
|
#define SPINAND_CMD_GET_FEATURE_CFG \
|
|
|
|
|
{ \
|
|
|
|
|
SPINAND_CMD_GET_FEATURE, 1, 1, 1, 0, 1 \
|
|
|
|
|
}
|
|
|
|
|
#define SPINAND_CMD_SET_FEATURE_CFG \
|
|
|
|
|
{ \
|
|
|
|
|
SPINAND_CMD_SET_FEATURE, 1, 1, 1, 0, 1 \
|
|
|
|
|
}
|
|
|
|
|
#define SPINAND_CMD_WR_ENABLE_CFG \
|
|
|
|
|
{ \
|
|
|
|
|
SPINAND_CMD_WR_ENABLE, 1, 0, 0, 0, 0 \
|
|
|
|
|
}
|
|
|
|
|
#define SPINAND_CMD_WR_DISABLE_CFG \
|
|
|
|
|
{ \
|
|
|
|
|
SPINAND_CMD_WR_DISABLE, 1, 0, 0, 0, 0 \
|
|
|
|
|
}
|
|
|
|
|
#define SPINAND_CMD_PROG_EXC_CFG \
|
|
|
|
|
{ \
|
|
|
|
|
SPINAND_CMD_PROG_EXC, 1, 3, 1, 0, 0 \
|
|
|
|
|
}
|
|
|
|
|
#define SPINAND_CMD_PAGE_READ_CFG \
|
|
|
|
|
{ \
|
|
|
|
|
SPINAND_CMD_PAGE_READ, 1, 3, 1, 0, 0 \
|
|
|
|
|
}
|
|
|
|
|
#define SPINAND_CMD_BLK_ERASE_CFG \
|
|
|
|
|
{ \
|
|
|
|
|
SPINAND_CMD_BLK_ERASE, 1, 3, 1, 0, 0 \
|
|
|
|
|
}
|
|
|
|
|
#define SPINAND_CMD_READ_ID_CFG \
|
|
|
|
|
{ \
|
|
|
|
|
SPINAND_CMD_READ_ID, 1, 0, 1, 1, 1 \
|
|
|
|
|
}
|
|
|
|
|
#define SPINAND_CMD_RESET_CFG \
|
|
|
|
|
{ \
|
|
|
|
|
SPINAND_CMD_RESET, 1, 0, 0, 0, 0 \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct spi_nand_cmd_cfg {
|
|
|
|
|
u8 opcode;
|
|
|
|
|
u8 opcode_bits;
|
|
|
|
|
u8 addr_bytes;
|
|
|
|
|
u8 addr_bits;
|
|
|
|
|
u8 dummy_bytes;
|
|
|
|
|
u8 data_bits;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* feature registers */
|
|
|
|
|
#define REG_BLOCK_LOCK 0xa0
|
|
|
|
|
#define REG_DIE_SELECT 0xd0
|
|
|
|
|
|
|
|
|
|
/* configuration register */
|
|
|
|
|
#define REG_CFG 0xb0
|
|
|
|
|
#define CFG_OTP_ENABLE BIT(6)
|
|
|
|
|
#define CFG_ECC_ENABLE BIT(4)
|
|
|
|
|
#define CFG_BUF_ENABLE BIT(3)
|
|
|
|
|
#define CFG_QUAD_ENABLE BIT(0)
|
|
|
|
|
|
|
|
|
|
/* status register */
|
2023-12-22 10:19:53 +08:00
|
|
|
#define REG_STATUS 0xc0
|
|
|
|
|
#define STATUS_BUSY BIT(0)
|
|
|
|
|
#define STATUS_ERASE_FAILED BIT(2)
|
|
|
|
|
#define STATUS_PROG_FAILED BIT(3)
|
|
|
|
|
|
|
|
|
|
#define STATUS_ECC_MASK GENMASK(5, 4)
|
|
|
|
|
#define STATUS_ECC_NO_BITFLIPS (0 << 4)
|
|
|
|
|
#define STATUS_ECC_HAS_1_4_BITFLIPS (1 << 4)
|
|
|
|
|
#define STATUS_ECC_UNCOR_ERROR (2 << 4)
|
2023-08-30 16:21:18 +08:00
|
|
|
|
|
|
|
|
#ifdef SPI_NAND_WINBOND
|
|
|
|
|
extern const struct spinand_manufacturer winbond_spinand_manufacturer;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SPI_NAND_XTX
|
|
|
|
|
extern const struct spinand_manufacturer xtx_spinand_manufacturer;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SPI_NAND_GIGADEVICE
|
|
|
|
|
extern const struct spinand_manufacturer gigadevice_spinand_manufacturer;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SPI_NAND_FORESEE
|
|
|
|
|
extern const struct spinand_manufacturer foresee_spinand_manufacturer;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SPI_NAND_TOSHIBA
|
|
|
|
|
extern const struct spinand_manufacturer toshiba_spinand_manufacturer;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SPI_NAND_MACRONIX
|
|
|
|
|
extern const struct spinand_manufacturer macronix_spinand_manufacturer;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SPI_NAND_ZETTA
|
|
|
|
|
extern const struct spinand_manufacturer zetta_spinand_manufacturer;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SPI_NAND_DOSILICON
|
|
|
|
|
extern const struct spinand_manufacturer dosilicon_spinand_manufacturer;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SPI_NAND_ETRON
|
|
|
|
|
extern const struct spinand_manufacturer etron_spinand_manufacturer;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SPI_NAND_MICRON
|
|
|
|
|
extern const struct spinand_manufacturer micron_spinand_manufacturer;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SPI_NAND_ZBIT
|
|
|
|
|
extern const struct spinand_manufacturer zbit_spinand_manufacturer;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SPI_NAND_ESMT
|
|
|
|
|
extern const struct spinand_manufacturer esmt_spinand_manufacturer;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SPI_NAND_UMTEK
|
|
|
|
|
extern const struct spinand_manufacturer umtek_spinand_manufacturer;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef SPI_NAND_QUANXING
|
|
|
|
|
extern const struct spinand_manufacturer quanxing_spinand_manufacturer;
|
|
|
|
|
#endif
|
2024-04-03 16:40:57 +08:00
|
|
|
#ifdef SPI_NAND_XINCUN
|
|
|
|
|
extern const struct spinand_manufacturer xincun_spinand_manufacturer;
|
|
|
|
|
#endif
|
2025-01-08 19:12:06 +08:00
|
|
|
#ifdef SPI_NAND_FUDANMICRO
|
|
|
|
|
extern const struct spinand_manufacturer fudanmicro_spinand_manufacturer;
|
|
|
|
|
#endif
|
2023-08-30 16:21:18 +08:00
|
|
|
|
2024-01-27 08:47:24 +08:00
|
|
|
extern struct spi_nand_cmd_cfg cmd_cfg_table[];
|
|
|
|
|
|
2023-08-30 16:21:18 +08:00
|
|
|
const struct aic_spinand_info *
|
2024-09-30 17:06:01 +08:00
|
|
|
spinand_match_and_init(u8 *devid, const struct aic_spinand_info *table,
|
2023-08-30 16:21:18 +08:00
|
|
|
u32 table_size);
|
|
|
|
|
int aic_spinand_transfer_message(struct aic_spinand *flash,
|
|
|
|
|
struct spi_nand_cmd_cfg *cfg, u32 addr,
|
|
|
|
|
u8 *sendBuff, u8 *recvBuff, u32 DataCount);
|
2025-01-08 19:12:06 +08:00
|
|
|
/* ooblayout
|
|
|
|
|
* distinguish the ECC protected bytes on the oob region
|
|
|
|
|
*/
|
|
|
|
|
int spinand_ooblayout_map_user(struct aic_spinand *flash, u8 *oobbuf,
|
|
|
|
|
const u8 *spare, int start, int nbytes);
|
|
|
|
|
int spinand_ooblayout_unmap_user(struct aic_spinand *flash, u8 *dst,
|
|
|
|
|
u8 *src, int start, int nbytes);
|
2023-08-30 16:21:18 +08:00
|
|
|
|
|
|
|
|
#endif /* __SPINAND_H__ */
|