Files
E3/e3_176_ref/drivers/include/sdrv_spi_nor.h
2025-10-21 19:40:27 +08:00

829 lines
30 KiB
C

/**
* @file sdrv_spi_nor.h
* @brief SemiDrive SPI Norflash driver header file.
*
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*/
#ifndef SDRV_SPI_NOR_H_
#define SDRV_SPI_NOR_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <types.h>
#include <sdrv_ckgen.h>
#include <sdrv_common.h>
#include <debug.h>
#undef BIT
#define BIT(nr) (1u << (nr))
#define SNOR_READID_DUMMY_LSB (24u)
#define SNOR_OPCODE_PROTO_LSB (24u)
#define SNOR_DTR_PROTO BIT(16)
#define SNOR_INST_LANS_PROTO_LSB (8u)
#define SNOR_INST_LANS_PROTO_MASK (0xFu)
#define SNOR_INST_SINGLE_LANS (0u << SNOR_INST_LANS_PROTO_LSB)
#define SNOR_INST_DUAL_LANS (1u << SNOR_INST_LANS_PROTO_LSB)
#define SNOR_INST_QUAD_LANS (2u << SNOR_INST_LANS_PROTO_LSB)
#define SNOR_INST_OCTAL_LANS (3u << SNOR_INST_LANS_PROTO_LSB)
#define SNOR_INST_LANS(x) (((x) >> SNOR_INST_LANS_PROTO_LSB) & \
(SNOR_INST_LANS_PROTO_MASK))
#define SNOR_ADDR_LANS_PROTO_LSB (4u)
#define SNOR_ADDR_LANS_PROTO_MASK (0xFu)
#define SNOR_ADDR_SINGLE_LANS (0u << SNOR_ADDR_LANS_PROTO_LSB)
#define SNOR_ADDR_DUAL_LANS (1u << SNOR_ADDR_LANS_PROTO_LSB)
#define SNOR_ADDR_QUAD_LANS (2u << SNOR_ADDR_LANS_PROTO_LSB)
#define SNOR_ADDR_OCTAL_LANS (3u << SNOR_ADDR_LANS_PROTO_LSB)
#define SNOR_ADDR_LANS(x) (((x) >> SNOR_ADDR_LANS_PROTO_LSB) & \
(SNOR_ADDR_LANS_PROTO_MASK))
#define SNOR_DATA_LANS_PROTO_LSB (0u)
#define SNOR_DATA_LANS_PROTO_MASK (0xFu)
#define SNOR_DATA_SINGLE_LANS (0u << SNOR_DATA_LANS_PROTO_LSB)
#define SNOR_DATA_DUAL_LANS (1u << SNOR_DATA_LANS_PROTO_LSB)
#define SNOR_DATA_QUAD_LANS (2u << SNOR_DATA_LANS_PROTO_LSB)
#define SNOR_DATA_OCTAL_LANS (3u << SNOR_DATA_LANS_PROTO_LSB)
#define SNOR_DATA_LANS(x) (((x) >> SNOR_DATA_LANS_PROTO_LSB) & \
(SNOR_DATA_LANS_PROTO_MASK))
#define SNOR_PROTO_1_1_1 \
(SNOR_INST_SINGLE_LANS | SNOR_ADDR_SINGLE_LANS | SNOR_DATA_SINGLE_LANS)
#define SNOR_PROTO_1_1_2 \
(SNOR_INST_SINGLE_LANS | SNOR_ADDR_SINGLE_LANS | SNOR_DATA_DUAL_LANS)
#define SNOR_PROTO_1_1_4 \
(SNOR_INST_SINGLE_LANS | SNOR_ADDR_SINGLE_LANS | SNOR_DATA_QUAD_LANS)
#define SNOR_PROTO_1_1_8 \
(SNOR_INST_SINGLE_LANS | SNOR_ADDR_SINGLE_LANS | SNOR_DATA_OCTAL_LANS)
#define SNOR_PROTO_1_2_2 \
(SNOR_INST_SINGLE_LANS | SNOR_ADDR_DUAL_LANS | SNOR_DATA_DUAL_LANS)
#define SNOR_PROTO_1_4_4 \
(SNOR_INST_SINGLE_LANS | SNOR_ADDR_QUAD_LANS | SNOR_DATA_QUAD_LANS)
#define SNOR_PROTO_1_8_8 \
(SNOR_INST_SINGLE_LANS | SNOR_ADDR_OCTAL_LANS | SNOR_DATA_OCTAL_LANS)
#define SNOR_PROTO_2_2_2 \
(SNOR_INST_DUAL_LANS | SNOR_ADDR_DUAL_LANS | SNOR_DATA_DUAL_LANS)
#define SNOR_PROTO_4_4_4 \
(SNOR_INST_QUAD_LANS | SNOR_ADDR_QUAD_LANS | SNOR_DATA_QUAD_LANS)
#define SNOR_PROTO_8_8_8 \
(SNOR_INST_OCTAL_LANS | SNOR_ADDR_OCTAL_LANS | SNOR_DATA_OCTAL_LANS)
#define SNOR_PROTO_1_1_1_DTR (SNOR_PROTO_1_1_1 | SNOR_DTR_PROTO)
#define SNOR_PROTO_1_2_2_DTR (SNOR_PROTO_1_2_2 | SNOR_DTR_PROTO)
#define SNOR_PROTO_1_4_4_DTR (SNOR_PROTO_1_4_4 | SNOR_DTR_PROTO)
#define SNOR_PROTO_4_4_4_DTR (SNOR_PROTO_4_4_4 | SNOR_DTR_PROTO)
#define SNOR_PROTO_1_1_8_DTR (SNOR_PROTO_1_1_8 | SNOR_DTR_PROTO)
#define SNOR_PROTO_1_8_8_DTR (SNOR_PROTO_1_8_8 | SNOR_DTR_PROTO)
#define SNOR_PROTO_8_8_8_DTR (SNOR_PROTO_8_8_8 | SNOR_DTR_PROTO)
#define SNOR_PROTO_DTR_MASK 0x1ffffu
#define SNOR_PROTO_MASK 0xffffu
#define SNOR_PROTO_DTR(x) ((x) & SNOR_PROTO_DTR_MASK)
#define SNOR_PROTO(x) ((x) & SNOR_PROTO_MASK)
#define SPI_NOR_MAX_ID_LEN 6
#define SECTOR_4K_POST (12)
#define SECTOR_32K_POST (15)
#define SECTOR_64K_POST (16)
#define SECTOR_128K_POST (17)
#define SECTOR_256K_POST (18)
#define SECTOR_POST_TO_SIZE(n) (1U << (n))
#define SPINOR_SECTOR_4K_SIZE (0x1000)
#define SPINOR_SECTOR_32K_SIZE (0x8000)
#define SPINOR_SECTOR_64K_SIZE (0x10000)
#define SPINOR_SECTOR_128K_SIZE (0x20000)
#define SPINOR_SECTOR_256K_SIZE (0x40000)
#define SWITCH_DEVICE_MAX_NUM (4u)
typedef enum {
SPI_NOR_SECTOR_4KB = 0,
SPI_NOR_SECTOR_32KB,
SPI_NOR_SECTOR_64KB,
SPI_NOR_SECTOR_128KB,
SPI_NOR_SECTOR_256KB,
SPI_NOR_SECTOR_TYPE_MAX,
} spi_nor_sector_type;
#define SECTOR_TYPE_TO_POST(type) ((type) ? (14 + (type)) : 12)
#define SECTOR_TYPE_TO_SIZE(type) SECTOR_POST_TO_SIZE(SECTOR_TYPE_TO_POST(type))
/**
* @brief flash addr/size use uint64_t.
*/
typedef uint64_t flash_addr_t;
typedef uint64_t flash_size_t;
/**
* @brief flash operating collection.
*/
enum flash_opt {
FLASH_OPT_NONE, /**< flash none opt */
FLASH_OPT_READ, /**< flash read opt */
FLASH_OPT_WRITE, /**< flash write opt */
FLASH_OPT_ERASE, /**< flash erase opt */
FLASH_OPT_MAX,
};
/**
* @brief flash operating result collection.
*/
enum flash_opt_result {
FLASH_OPT_COMPLETE = 0, /**< last transfer success flag */
FLASH_OPT_FAILED, /**< last tansfer failed flag */
FLASH_OPT_PENDING, /**< last tansfer not complete flag */
FLASH_OPT_INCONSISTENT, /**< last tansfer data error flag */
FLASH_OPT_INVALID, /**< last tansfer invalid flag */
FLASH_OPT_RESULET_MAX,
};
/**
* @brief flash transfer collection.
*/
struct flash_xfer_info {
enum flash_opt opt_type; /**< flash r/w/e opt */
enum flash_opt_result opt_result; /**< flash opt result */
flash_addr_t addr; /**< flash address */
uint8_t *buf; /**< flash r/w to buf address */
flash_size_t size; /**< flash opt size */
};
/**
* @brief event callback.
*/
typedef void (*flash_notification)(enum flash_opt type,
enum flash_opt_result result);
/**
* @brief reserve.
*/
enum xspi_xfer_mode {
XSPI_XFER_NONE = 0,
XSPI_XFER_READ,
XSPI_XFER_WRITE,
};
/**
* @brief reserve for osEvent interface.
*/
enum xspi_bus_event_mode {
SPI_NOR_XFER_CLEAR,
SPI_NOR_XFER_COMPLETE = 1,
SPI_NOR_XFER_WAIT,
};
/**
* @brief xspi config collection
*/
struct xspi_config {
uint8_t id; /**< xspi config id */
addr_t apb_base; /**< xspi config apb address */
addr_t direct_base; /**< xspi config direct transmission base address */
unsigned int irq; /**< xspi config irq number */
unsigned long ref_clk; /**< xspi config reference clk */
bool xip_mode; /**< device is xip mode */
};
/**
* @brief xspi private information.
*/
struct xspi_pdata {
uint8_t id; /**< xspi config id */
addr_t apb_base; /**< xspi config apb address */
addr_t direct_base; /**< xspi config direct transmission base address */
unsigned int irq; /**< xspi config irq number */
unsigned long ref_clk_hz; /**< xspi config reference clk */
unsigned int sclk; /**< reverse */
uint8_t dma_bus_width; /**< dma bus width */
uint32_t dma_burst_size; /**< dma burst length */
bool cs_decoded; /**< reverse */
uint8_t current_cs; /**< xspi using cs num */
bool dqs_en; /**< dqs enable for device&&host */
uint8_t fifo_depth; /**< xspi fifo depth */
uint8_t fifo_width; /**< xspi fifo width */
uint32_t direct_range_size; /**<direct trans range size */
};
struct spi_nor;
/**
* @brief sub group
*/
typedef enum {
SPI_NOR_COMMON = 0, // ret = OK
SPI_NOR_INIT,
SPI_NOR_ERASE,
SPI_NOR_WRITE,
SPI_NOR_READ,
SPI_NOR_CANCEL,
} spi_nor_error_group_t;
/**
* @brief Common error code:
*/
typedef enum {
SPI_NOR_OK = 0,
SPI_NOR_FAIL,
SPI_NOR_BUSY,
SPI_NOR_TIMEOUT,
SPI_NOR_UNSUPPORT,
SPI_NOR_UNREACHABLE,
SPI_NOR_ADDRESS_INVALID,
SPI_NOR_LENGTH_INVALID,
SPI_NOR_COMMON_CODE_MAX,
} spi_nor_common_error_code_t;
/**
* @brief error code for init
*/
typedef enum {
SPI_NOR_INIT_TRAIN_E = SPI_NOR_COMMON_CODE_MAX,
} spi_nor_init_error_code_t;
#define SPI_NOR_OK_STATUS SDRV_STATUS_OK
#define SPI_NOR_ERR_CODE(g, c) (((((g) & 0xF) << 5) | ((c) & 0x1F)) * !!(c))
#define SPI_NOR_ERR_STATUS(g, c) (int)(SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_XSPI, SPI_NOR_ERR_CODE((g), (c))) * !!(c))
/**
* @brief spi norflash trans mode, dma/intterrupt/polling.
*/
enum spi_nor_xfer_mode {
SPI_NOR_XFER_POLLING_MODE = 0,
SPI_NOR_XFER_INTERRUPT_MODE,
SPI_NOR_XFER_DMA_MODE,
};
/**
* @brief device trans mode.
*/
enum spi_nor_device_mode {
SPI_NOR_DEV_SINGLE_MODE = 0,
SPI_NOR_DEV_LOCKSTEP_MODE,
SPI_NOR_DEV_PARALLEL_MODE,
};
/**
* @brief spi norflash proto type.
*/
enum spi_nor_proto_type {
SPI_NOR_PROTO_TYPE_READ = 0,
SPI_NOR_PROTO_TYPE_WRITE,
SPI_NOR_PROTO_TYPE_ERASE,
};
/**
* @brief spi norflash device type.
*/
enum spi_memory_type {
SPI_AUTO_DETECT = 0,
SPI_NOR_FLASH,
SPI_NAND_FLASH,
SPI_HYPERFLASH,
SPI_HYPERRAM,
SPI_HYPERBUS_MCP,
};
/**
* @brief spi norflash cmd.
*/
struct spi_nor_cmd {
uint8_t opcode; /**< spi nor opcode */
uint8_t inst_type; /**< proto */
uint8_t dummy; /**< cmd config dummy */
uint8_t addr_bytes; /**< 0 bytes(no need addr) 3 bytes or 4 bytes */
};
/**
* @brief address data, set pre transaction to hyperflash.
*/
struct hyperbus_ca {
uint16_t addr;
uint16_t data;
};
/**
* @brief hyperflash cmd.
*/
struct hyperflash_cmd {
char *name; /**< hyperflash name */
bool is_read; /**< read or write */
uint32_t num; /**< cmd/address nums */
struct hyperbus_ca ca[7];
};
/**
* @brief spi norflash r/w/e ops flags.
*/
enum spi_nor_ops {
SPI_NOR_OPS_READ = 1,
SPI_NOR_OPS_WRITE,
SPI_NOR_OPS_ERASE,
SPI_NOR_OPS_LOCK,
SPI_NOR_OPS_UNLOCK,
};
/**
* @brief spi norflash indirect/direct(r/w) flags.
*/
enum spi_nor_rw_para {
SPI_NOR_DIRECT_READ = 0,
SPI_NOR_INDIRECT_READ,
SPI_NOR_DIRECT_WRITE,
SPI_NOR_INDIRECT_WRITE,
};
/**
* @brief spi norflash configurations.
*/
struct spi_nor_config {
uint8_t id; /**< config id */
uint8_t cs; /**< config chip selet */
uint32_t baudrate; /**< config baudrate */
enum spi_nor_xfer_mode xfer_mode; /**< trans mode, dma/intterrupt/polling */
enum spi_nor_device_mode dev_mode; /**< device trans mode LOCKSTEP/PARALLEL/SINGLE */
enum spi_memory_type mem_type; /**< flash device type */
bool async_mode; /**< use async mode */
bool hyperbus_mode; /**< hyperbus mode */
bool sw_rst; /**< softwate reset device */
uint32_t force_size; /**< spi nor force size */
};
struct spi_nor_erase_map {
uint32_t erase_proto;
uint32_t erase_size; // in bytes
uint32_t post;
};
struct spi_nor_erase_cmd {
flash_addr_t addr;
const struct spi_nor_erase_map *map;
};
/**
* @brief spi norflash information.
*/
struct flash_info {
const char *name; /**< flash name */
uint8_t flash_id[SPI_NOR_MAX_ID_LEN]; /**< get flash id */
uint32_t read_proto; /**< falsh read transmission proto */
uint32_t write_proto; /**< falsh write transmission proto */
uint32_t erase_proto; /**< default falsh erase transmission proto */
uint32_t erase_proto_list[SPI_NOR_SECTOR_TYPE_MAX]; /**< support falsh erase transmission protos */
uint8_t read_dummy; /**< falsh read dummy, it depends on the frequency */
uint8_t write_dummy; /**< falsh write dummy, it depends on the frequency */
uint8_t status_dummy; /**< falsh get status dummy */
uint32_t sector_size; /**< flash sector size, general 4K or 256K */
uint16_t page_size; /**< flash page size, general 256byte */
flash_size_t size; /**< get flash capacity, get from flash_id */
struct spi_nor_erase_map erase_map[SPI_NOR_SECTOR_TYPE_MAX]; /**< Automatic filling */
/**< they depend on flash support */
int (*default_init)(struct spi_nor *nor); /**< initialize dummy for different flash */
int (*octal_dtr_enable)(struct spi_nor *nor, bool enable); /**< initialize octal dtr mode */
int (*quad_enable)(struct spi_nor *nor, bool enable); /**< initialize quad mode */
int (*enter_quad)(struct spi_nor *nor, bool enable); /**< initialize qpi mode */
int (*set_4byte_addr_mode)(struct spi_nor *nor,
bool enable); /**< initialize 4byte address mode */
};
/**
* @brief spi norflash host operation.
*/
struct spi_nor_host_ops {
int (*prepare)(struct spi_nor *flash_handle, enum spi_nor_ops ops); /**< prepare operations before r/w/e setup */
void (*unprepare)(struct spi_nor *flash_handle, enum spi_nor_ops ops); /**< operation after r/w/e setup */
int (*reg_read)(struct spi_nor *flash_handle, struct spi_nor_cmd *cmd,
flash_addr_t addr, uint8_t *buf, flash_size_t length); /**< spi nor read register address operation */
int (*reg_write)(struct spi_nor *flash_handle, struct spi_nor_cmd *cmd,
flash_addr_t addr, const uint8_t *buf,
flash_size_t length); /**< spi nor write register address operation */
int (*read)(struct spi_nor *flash_handle, flash_addr_t addr, uint8_t *buf,
flash_size_t length); /**< spi nor read flash address operation */
int (*write)(struct spi_nor *flash_handle, flash_addr_t addr,
const uint8_t *buf, flash_size_t length); /**< spi nor write flash address operation */
int (*erase)(struct spi_nor *flash_handle, flash_addr_t offset); /**< spi nor erase flash address operation */
int (*complex_erase)(struct spi_nor *nor, struct spi_nor_erase_cmd *cmd); /**< spi nor erase flash cmd operation */
int (*training)(struct spi_nor *flash_handle, flash_addr_t addr,
uint8_t *buf, const uint8_t *pattern, flash_size_t length); /**< spi nor init training flash address operation */
int (*cancel)(struct spi_nor *flash_handle); /**< spi nor cancel operation */
void (*cache_flush)(struct spi_nor *flash_handle, flash_addr_t addr, flash_size_t length); /**< spi nor host flush cache operation */
int (*enable_rfd)(struct spi_nor *flash_handle, uint8_t mask); /**< spi nor host enable rfd operation */
void (*xip_proto_setup)(struct spi_nor *flash_handle); /**< spi nor xip mode proto setup */
};
/**
* @brief hyperbus host operation.
*/
struct hyperbus_host_ops {
int (*read16)(struct spi_nor *flash_handle, flash_addr_t addr, uint16_t *buf); /**< hyperbus read register operation */
int (*write16)(struct spi_nor *flash_handle, flash_addr_t addr, uint16_t *buf); /**< hyperbus write register operation */
void (*set_pre_transaction)(struct spi_nor *flash_handle, bool is_read,
bool is_direct, uint32_t num, struct hyperbus_ca **ca_array); /**< hyperbus read/write register prepare operation */
void (*hyperram_en)(struct spi_nor *flash_handle, uint8_t cs,
uint8_t read_dummy, uint8_t write_dummy); /**< hyperram enable operation */
int (*read)(struct spi_nor *flash_handle, flash_addr_t addr, uint8_t *buf,
flash_size_t length); /**< hyper read operation */
int (*write)(struct spi_nor *flash_handle, flash_addr_t addr,
const uint8_t *buf, flash_size_t length); /**< hyper write operation */
void (*cache_flush)(struct spi_nor *flash_handle, flash_addr_t addr, flash_size_t length); /**< hyper flush cache operation */
};
/**
* @brief spi norflash host configurations.
*/
struct spi_nor_host {
uint8_t id; /**< xspi host id */
addr_t base; /**< xspi apb base address */
unsigned int irq; /**< xspi irq number */
sdrv_ckgen_node_t *clk; /**< get host ckgen node */
unsigned long ref_clk_hz; /**< xspi reference clk */
bool xip_mode; /**< device is xip mode */
struct spi_nor_host_ops *ops; /**< xspi nor host ops */
struct hyperbus_host_ops *hyper_ops; /**< hyperbus host ops */
struct spi_nor *dev; /**< spi_nor info */
void *priv_data; /**< xspi private info */
struct spi_nor *nor_tab[SWITCH_DEVICE_MAX_NUM]; /**< spi_nor binded */
flash_size_t total_size; /**< all flash size */
};
/**
* @brief dma operation for xspi.
*/
typedef void (*flash_dma_config)(struct spi_nor *nor, flash_addr_t addr, uint8_t *buf,
uint32_t len, bool is_read_flag, uint32_t burst_len);
typedef void (*flash_dma_stop)(void);
typedef void (*flash_dma_stop_signal)(struct spi_nor *nor);
/**
* @brief spi norflash device configurations.
*/
struct spi_nor {
uint8_t id; /**< spi nor id */
uint8_t cs; /**< spi nor cs signal */
uint32_t baudrate; /**< spi nor baudrate */
uint32_t offset_address; /**< spi nor offset address */
enum spi_memory_type
mem_type; /**< get type HYPERRAM/HYPERFLASH/HYPERBUS_MCP/NORFLASH */
enum spi_nor_device_mode dev_mode; /**< dev mode LOCKSTEP/PARALLEL/SINGLE */
struct flash_info info; /**< flash info */
bool phy_en; /**< phy en,turn it on for flash training use it */
bool dqs_en; /**< dqs enable for device&&host */
bool octal_dtr_en; /**< octal dtr mode enable for device&&host */
bool async_mode; /**< async mode selet */
bool hyperbus_mode; /**< hyperbus mode selet */
bool sw_rst; /**< sw reset selet in flash init */
uint32_t reg_proto; /**< r/w/e transmission proto */
uint8_t addr_width; /**< r/w/e transmission address width */
enum spi_nor_xfer_mode xfer_mode; /**< transmission mode dma/intterrupt/polling */
struct flash_xfer_info xfer_info; /**< flash info to spi device */
struct flash_xfer_info xfer_info_bottom; /**< flash info to spi device */
flash_notification event_handler; /**< event callback */
flash_dma_config dma_xfer_config; /**< dma config callback */
flash_dma_stop dma_xfer_stop; /**< dma stop callback */
flash_dma_stop_signal dma_stop; /**< dma single channel stop callback */
struct spi_nor_host *host; /**< host struct, operate the device */
void *ops; /**< flash_ops_t */
void *parent; /**< reverse */
};
typedef struct {
int (*fls_wait_idle)(struct spi_nor *nor);
int (*fls_write_enable)(struct spi_nor *nor, bool enable);
int (*fls_init)(struct spi_nor *nor, struct spi_nor_host *host,
const struct spi_nor_config *flash_config);
void (*fls_deinit)(struct spi_nor *nor);
int (*fls_read)(struct spi_nor *nor, flash_addr_t addr, uint8_t *buf,
flash_size_t size);
int (*fls_write)(struct spi_nor *nor, flash_addr_t addr,
const uint8_t *buf, flash_size_t size);
int (*fls_erase)(struct spi_nor *nor, flash_addr_t addr,
flash_size_t size);
int (*fls_cancel)(struct spi_nor *nor);
void (*fls_main_function)(struct spi_nor *nor);
const struct flash_info*(*fls_get_flash_table)(uint32_t *num);
} flash_ops_t;
#if !(CONFIG_DISABLE_SPIBUS_COMPILE)
extern flash_ops_t spi_nor_ops;
#endif
#if !(CONFIG_DISABLE_HYPERBUS_COMPILE)
extern flash_ops_t hyperbus_ops;
#endif
/**
* @brief spi norflash get status.
* @param[in] nor spi norflash instance contex handle.
* @retval 0: success
* @retval other: failed
*/
static inline int sdrv_spi_nor_wait_idle(struct spi_nor *nor) {
if (nor && nor->ops) {
return ((flash_ops_t*)(nor->ops))->fls_wait_idle(nor);
}
return SDRV_STATUS_INVALID_PARAM;
}
/**
* @brief spi norflash write enable op.
* @param[in] nor spi norflash instance contex handle.
* @param[in] enable spi norflash write enable or not .
* @retval 0: success
* @retval other: failed
*/
static inline int sdrv_spi_nor_write_enable(struct spi_nor *nor, bool enable) {
if (nor && nor->ops) {
return ((flash_ops_t*)(nor->ops))->fls_write_enable(nor, enable);
}
return SDRV_STATUS_INVALID_PARAM;
}
/**
* @brief spi norflash host initialize function.
* @details This function used for before any other spi nor APIs.
* @param[in] host_config spi norflash host config data, will not used after function return, so this param can be in stack.
* @return void* The host platform data.
* @retval Null: failed
* @retval other: success.
*/
//void *spi_nor_host_init(const struct spi_nor_host_config *host_config);
/**
* @brief spi norflash instance initialization interface.
* @details This function must used after spi_nor_host_init and before other APIs.
* @param[in, out] flash_handle spi norflash instance contex handle, the data memory need alloc by user.
* @param[in] flash_config spi norflash device config data, will not used after function return, so this param can be in stack.
* @return int
* @retval 0: success
* @retval other: failed
*/
static inline int sdrv_spi_nor_init(struct spi_nor *flash_handle, struct spi_nor_host *host,
const struct spi_nor_config *flash_config) {
int ret = -1;
if (flash_config->hyperbus_mode) {
#if !(CONFIG_DISABLE_HYPERBUS_COMPILE)
ret = hyperbus_ops.fls_init(flash_handle, host, flash_config);
#endif
} else {
#if !(CONFIG_DISABLE_SPIBUS_COMPILE)
ret = spi_nor_ops.fls_init(flash_handle, host, flash_config);
#endif
}
return ret;
}
/**
* @brief spi norflash instance destruction interface.
* @param[in] flash_handle spi norflash instance contex handle.
*/
static inline void sdrv_spi_nor_deinit(struct spi_nor *flash_handle) {
ssdk_printf(SSDK_CRIT, "sdrv_spi_nor_deinit!\r\n");
// ssdk_printf(SSDK_INFO,"flash_handle: %d,flash_handle->ops: %d \r\n", flash_handle, flash_handle->ops);
ssdk_printf(SSDK_CRIT, "flash_handle :0x%x,handle->ops: :0x%x,\r\n",flash_handle, flash_handle->ops);
if (flash_handle && flash_handle->ops)
{
((flash_ops_t*)(flash_handle->ops))->fls_deinit(flash_handle);
}
}
/**
* @brief spi norflash read interface.
* @details When the buffer and read size aligned with cacheline size will provide best performance.
* @param[in] flash_handle spi norflash instance contex handle.
* @param[in] addr spi norflash addr.
* @param[in] buf Read buffer, alloc by user.
* @param[in] size Read size, need aligned with 4bytes for dma limit.
* @return int
* @retval 0: success
* @retval other: failed
*/
static inline int sdrv_spi_nor_read(struct spi_nor *flash_handle, flash_addr_t addr,
uint8_t *buf,
flash_size_t size) {
if (flash_handle && flash_handle->ops) {
return ((flash_ops_t*)(flash_handle->ops))->fls_read(flash_handle, addr, buf, size);
}
return SDRV_STATUS_INVALID_PARAM;
}
/**
* @brief spi norflash write interface.
* @details When the buffer and write size aligned with cacheline size will provide best performance.
* @param[in] flash_handle spi norflash instance contex handle.
* @param[in] addr spi norflash addr.
* @param[in] buf Write buffer, alloc by user.
* @param[in] size Read size, need aligned with 4bytes for dma limit.
* @return int
* @retval 0: success
* @retval other: failed
*/
static inline int sdrv_spi_nor_write(struct spi_nor *flash_handle, flash_addr_t addr,
const uint8_t *buf, flash_size_t size) {
if (flash_handle && flash_handle->ops) {
return ((flash_ops_t*)(flash_handle->ops))->fls_write(flash_handle, addr, buf, size);
}
return SDRV_STATUS_INVALID_PARAM;
}
/**
* @brief spi norflash erase interface.
* @param[in] flash_handle spi norflash instance contex handle.
* @param[in] addr spi norflash addr.
* @param[in] size Erase size, need aligned with sector_size what get by sdrv_spi_nor_get_info API.
* @return int
* @retval 0: success
* @retval other: failed
*/
static inline int sdrv_spi_nor_erase(struct spi_nor *flash_handle, flash_addr_t addr,
flash_size_t size) {
if (flash_handle && flash_handle->ops) {
return ((flash_ops_t*)(flash_handle->ops))->fls_erase(flash_handle, addr, size);
}
return SDRV_STATUS_INVALID_PARAM;
}
/**
* @brief spi norflash async cancel interface.
* @details Used for cancel the last tansfer what like read write or erase.
* @param[in] flash_handle spi norflash instance contex handle.
* @return int
* @retval 0: success
* @retval other: failed
*/
static inline int sdrv_spi_nor_cancel(struct spi_nor *flash_handle) {
if (flash_handle && flash_handle->ops) {
return ((flash_ops_t*)(flash_handle->ops))->fls_cancel(flash_handle);
}
return SDRV_STATUS_INVALID_PARAM;
}
/**
* @brief spi norflash async main function interface.
* @details When use async mode, this function need be called cyclically.
* @param[in] flash_handle spi norflash instance contex handle.
*/
static inline void sdrv_spi_nor_main_function(struct spi_nor *flash_handle) {
if (flash_handle && flash_handle->ops) {
((flash_ops_t*)(flash_handle->ops))->fls_main_function(flash_handle);
}
}
/**
* @brief Used for setup spi norflash async mode notification handler.
* @details When use async mode, user can selet passive notification mode or active query mode.
* @param[in] flash_handle spi norflash instance contex handle.
* @param[in] handler flash notification handler.
*/
static inline void sdrv_spi_nor_setup_handler(struct spi_nor *flash_handle,
flash_notification handler)
{
flash_handle->event_handler = handler;
return;
}
/**
* @brief Used for get spi norflash async tansfer result.
* @param[in] flash_handle spi norflash instance contex handle.
* @return enum flash_opt_result
* @retval FLASH_OPT_COMPLETE: last transfer success
* @retval FLASH_OPT_FAILED: last tansfer failed
* @retval FLASH_OPT_PENDING: last tansfer not complete
* @retval FLASH_OPT_INCONSISTENT: last tansfer data error
* @retval FLASH_OPT_INVALID: last tansfer invalid
*/
static inline enum flash_opt_result sdrv_spi_nor_get_result(
struct spi_nor *flash_handle)
{
if (flash_handle) {
return flash_handle->xfer_info.opt_result;
}
else {
return FLASH_OPT_INVALID;
}
}
/**
* @brief Used for get spi norflash info what like sector size, page size, and ect.
* @param[in] flash_handle spi norflash instance contex handle.
* @return struct flash_info* Norflash info data.
*/
static inline struct flash_info *sdrv_spi_nor_get_info(struct spi_nor
*flash_handle)
{
if (flash_handle) {
return &(flash_handle->info);
}
else {
return NULL;
}
}
static inline int sdrv_spi_nor_enable_rfd(struct spi_nor *flash_handle, uint8_t mask) {
int ret;
if (flash_handle && flash_handle->host->ops->enable_rfd) {
flash_handle->host->ops->prepare(flash_handle, SPI_NOR_OPS_LOCK);
ret = flash_handle->host->ops->enable_rfd(flash_handle, mask);
flash_handle->host->ops->unprepare(flash_handle, SPI_NOR_OPS_LOCK);
if (ret) {
return SDRV_STATUS_FAIL;
}
} else {
return SDRV_STATUS_INVALID_PARAM;
}
return SDRV_STATUS_OK;
}
static inline const struct flash_info *sdrv_spi_nor_get_flash_table(
bool is_hyperbus, uint32_t *num) {
const struct flash_info *ret = NULL;
if (!num) {
return NULL;
}
if (is_hyperbus) {
#if !(CONFIG_DISABLE_HYPERBUS_COMPILE)
ret = hyperbus_ops.fls_get_flash_table(num);
#endif
} else {
#if !(CONFIG_DISABLE_SPIBUS_COMPILE)
ret = spi_nor_ops.fls_get_flash_table(num);
#endif
}
return ret;
}
static inline struct spi_nor *sdrv_get_flash_handle(struct spi_nor_host *host,
flash_addr_t addr, flash_size_t size) {
struct spi_nor *nor;
for (uint8_t i = 0; i < SWITCH_DEVICE_MAX_NUM ; i++) {
nor = host->nor_tab[i];
if (!nor) {
continue;
}
if ((addr >= nor->offset_address) &&
(addr + size) <= (nor->offset_address + nor->info.size)) {
return nor;
}
}
return NULL;
}
static inline int sdrv_host_read(struct spi_nor_host *host, flash_addr_t addr,
uint8_t *buf, flash_size_t size) {
struct spi_nor *flash_handle = sdrv_get_flash_handle(host, addr, size);
if (flash_handle) {
addr -= flash_handle->offset_address;
return sdrv_spi_nor_read(flash_handle, addr, buf, size);
}
return SDRV_STATUS_FAIL;
}
static inline int sdrv_host_erase(struct spi_nor_host *host, flash_addr_t addr,
flash_size_t size) {
struct spi_nor *flash_handle = sdrv_get_flash_handle(host, addr, size);
if (flash_handle) {
addr -= flash_handle->offset_address;
return sdrv_spi_nor_erase(flash_handle, addr, size);
}
return SDRV_STATUS_FAIL;
}
static inline int sdrv_host_write(struct spi_nor_host *host, flash_addr_t addr,
const uint8_t *buf, flash_size_t size) {
struct spi_nor *flash_handle = sdrv_get_flash_handle(host, addr, size);
if (flash_handle) {
addr -= flash_handle->offset_address;
return sdrv_spi_nor_write(flash_handle, addr, buf, size);
}
return SDRV_STATUS_FAIL;
}
#ifdef __cplusplus
}
#endif
#endif /* SDRV_SPI_NOR_H_ */