From 6b2c5264731154c1db6a00e87e4b196ba9e46910 Mon Sep 17 00:00:00 2001 From: "yuhuan.du" Date: Tue, 6 Jun 2023 10:12:57 +0800 Subject: [PATCH] [Add] add sfc nor driver for x2600 --- drivers/drivers-x2600/include/x2600_hal_sfc.h | 182 ++- drivers/drivers-x2600/include/x2600_ll_sfc.h | 360 ++++- drivers/drivers-x2600/src/x2600_hal_sfc.c | 1340 ++++++++++++++++- drivers/drivers-x2600/src/x2600_ll_sfc.c | 537 ++++++- .../icodec}/include/board_eth_phy_conf.h | 0 .../Examples/icodec}/include/x2600_hal_conf.h | 24 +- .../icodec}/include/x2600_sysclk_conf.h | 0 7 files changed, 2311 insertions(+), 132 deletions(-) rename {drivers/drivers-x2600 => projects/x2660-halley/Examples/icodec}/include/board_eth_phy_conf.h (100%) rename {drivers/drivers-x2600 => projects/x2660-halley/Examples/icodec}/include/x2600_hal_conf.h (96%) rename {drivers/drivers-x2600 => projects/x2660-halley/Examples/icodec}/include/x2600_sysclk_conf.h (100%) diff --git a/drivers/drivers-x2600/include/x2600_hal_sfc.h b/drivers/drivers-x2600/include/x2600_hal_sfc.h index 61c82eda..cc954856 100755 --- a/drivers/drivers-x2600/include/x2600_hal_sfc.h +++ b/drivers/drivers-x2600/include/x2600_hal_sfc.h @@ -11,7 +11,7 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ - + #ifndef __X2600_HAL_SFC_H__ #define __X2600_HAL_SFC_H__ @@ -28,138 +28,256 @@ * @addtogroup g_X2600_SFC_HAL_Driver SFC HAL 驱动 * @{ */ - + /* 1. 头文件 (Includes)----------------------------------------------- */ -//删除此行,添加内容 -//删除此行,添加内容 +#include "x2600_hal_def.h" +#include "x2600_ll_sfc.h" /* 2. 导出的类型 (Exported Types)--------------------------------------- */ /** * @defgroup SFC_exported_types SFC 导出的类型 (Exported Types) * @{ */ - -// 删除此行, 添加内容 -// 删除此行, 添加内容 + +typedef enum { + HAL_SFCNOR_STATE_RESET = 0x00U, /*!< NOR not yet initialized or disabled */ + HAL_SFCNOR_STATE_READY = 0x01U, /*!< NOR initialized and ready for use */ + HAL_SFCNOR_STATE_BUSY = 0x02U, /*!< NOR internal processing is ongoing */ + HAL_SFCNOR_STATE_ERROR = 0x03U, /*!< NOR error state */ + HAL_SFCNOR_STATE_PROTECTED = 0x04U /*!< NOR NORSRAM device write protected */ +} HAL_SFCNOR_StateTypeDef; + +typedef struct { +} SFCNOR_InitTypeDef; + +typedef struct __SFCNOR_HandleTypeDef { + SFC_TypeDef *Instance; /*!< SFC register base address*/ + + SFCNOR_InitTypeDef Init; /*!< parameters.*/ + + struct spi_nor_info spi_nor_info; + + struct norflash_partitions norflash_partitions; + + struct sfc_cdt_xfer xfer; + + OperationMode in_mode; + + int quad_succeed; + + uint32_t pEAddress; + + uint32_t Elen; /*!< SFCNOR erase len */ + + uint32_t pTxAddress; + + uint8_t *pTxBuffPtr; /*!< Pointer to SFCNOR Tx transfer Buffer */ + + uint32_t TxXferSize; /*!< SFCNOR Tx Transfer size */ + + __IO HAL_SFCNOR_StateTypeDef State; /*!< NOR device access state */ + +#if (USE_HAL_SFCNOR_REGISTER_CALLBACKS == 1) + void (* MspInitCallback)(struct __SFCNOR_HandleTypeDef *hnor); /*!< NOR Msp Init callback */ + void (* MspDeInitCallback)(struct __SFCNOR_HandleTypeDef *hnor); /*!< NOR Msp DeInit callback */ + void (* EraseFinishCallback)(struct __SFCNOR_HandleTypeDef *hnor); + void (* WriteFinishCallback)(struct __SFCNOR_HandleTypeDef *hnor); + void (* ReadFinishCallback)(struct __SFCNOR_HandleTypeDef *hnor); + void (* ErrorCallback)(struct __SFCNOR_HandleTypeDef *hnor); +#endif +} SFCNOR_HandleTypeDef; + + +#if (USE_HAL_SFCNOR_REGISTER_CALLBACKS == 1) +/** + * @brief HAL NOR Callback ID enumeration definition + */ +typedef enum { + HAL_SFCNOR_MSP_INIT_CB_ID = 0x00U, /*!< NOR MspInit Callback ID */ + HAL_SFCNOR_MSP_DEINIT_CB_ID = 0x01U, /*!< NOR MspDeInit Callback ID */ + + HAL_SFCNOR_ERASE_FINISH_CB_ID = 0x10U, /*!< NOR Erase Complete Callback ID */ + HAL_SFCNOR_WRITE_FINISH_CB_ID = 0x11U, /*!< NOR Write Complete Callback ID */ + HAL_SFCNOR_READ_FINISH_CB_ID = 0x12U, /*!< NOR Read Complete Callback ID */ + HAL_SFCNOR_ERROR_CB_ID = 0x13U /*!< NOR Error Callback ID */ +} HAL_SFCNOR_CallbackIDTypeDef; + +/** + * @brief HAL NOR Callback pointer definition + */ +typedef void (*pSFCNOR_CallbackTypeDef)(SFCNOR_HandleTypeDef *hnor); +#endif /** * @} - */ + */ /* 3. 导出常量定义 Exported Constants ----------------------------------- */ /** * @defgroup SFC_exported_constants SFC 导出的常量 Exported Constants * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 4. 导出宏定义 Exported Macros --------------------------------------- */ /** * @defgroup SFC_exported_macros SFC 导出宏 Exported Macros * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 5. 导出函数申明 Exported Funcs --------------------------------------- */ /** * @defgroup SFC_exported_funcs SFC 导出函数申明 Exported Funcs * @{ */ - -// 删除此行, 添加内容 -// 删除此行, 添加内容 + +HAL_StatusTypeDef HAL_SFCNOR_Init(SFCNOR_HandleTypeDef *hnor); +HAL_StatusTypeDef HAL_SFCNOR_Init_IT(SFCNOR_HandleTypeDef *hnor); +HAL_StatusTypeDef HAL_SFCNOR_Init_PIO_DMA(SFCNOR_HandleTypeDef *hnor); +HAL_StatusTypeDef HAL_SFCNOR_Init_IT_DMA(SFCNOR_HandleTypeDef *hnor); +HAL_StatusTypeDef HAL_SFCNOR_DeInit(SFCNOR_HandleTypeDef *hnor); +void HAL_SFCNOR_MspInit(SFCNOR_HandleTypeDef *hnor); +void HAL_SFCNOR_MspDeInit(SFCNOR_HandleTypeDef *hnor); +void HAL_SFCNOR_MspWait(SFCNOR_HandleTypeDef *hnor, uint32_t Timeout); +void HAL_SFCNOR_EraseFinishCallback(SFCNOR_HandleTypeDef *hnor); +void HAL_SFCNOR_WriteFinishCallback(SFCNOR_HandleTypeDef *hnor); +void HAL_SFCNOR_ReadFinishCallback(SFCNOR_HandleTypeDef *hnor); +void HAL_SFCNOR_ErrorCallback(SFCNOR_HandleTypeDef *hnor); + +void HAL_SFCNOR_IRQHandler(int irq, void *data); + +HAL_StatusTypeDef HAL_SFCNOR_Read_ID(SFCNOR_HandleTypeDef *hnor, unsigned int *pNOR_ID); +HAL_StatusTypeDef HAL_SFCNOR_Read(SFCNOR_HandleTypeDef *hnor, uint32_t pAddress, uint32_t len, unsigned char *pData); +HAL_StatusTypeDef HAL_SFCNOR_Program(SFCNOR_HandleTypeDef *hnor, uint32_t pAddress, uint32_t len, unsigned char *pData); +HAL_StatusTypeDef HAL_SFCNOR_Erase_Block(SFCNOR_HandleTypeDef *hnor, uint32_t pAddress, uint32_t len); +HAL_StatusTypeDef HAL_SFCNOR_Read_IT(SFCNOR_HandleTypeDef *hnor, uint32_t pAddress, uint32_t len, unsigned char *pData); +HAL_StatusTypeDef HAL_SFCNOR_Program_IT(SFCNOR_HandleTypeDef *hnor, uint32_t pAddress, uint32_t len, unsigned char *pData); +HAL_StatusTypeDef HAL_SFCNOR_Erase_Block_IT(SFCNOR_HandleTypeDef *hnor, uint32_t pAddress, uint32_t len); +HAL_StatusTypeDef HAL_SFCNOR_Erase_Chip(SFCNOR_HandleTypeDef *hnor); +HAL_SFCNOR_StateTypeDef HAL_SFCNOR_GetState(SFCNOR_HandleTypeDef *hnor); + +#if (USE_HAL_SFCNOR_REGISTER_CALLBACKS == 1) +/* NOR callback registering/unregistering */ +HAL_StatusTypeDef HAL_SFCNOR_RegisterCallback(SFCNOR_HandleTypeDef *hnor, HAL_SFCNOR_CallbackIDTypeDef CallbackId, pSFCNOR_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_SFCNOR_UnRegisterCallback(SFCNOR_HandleTypeDef *hnor, HAL_SFCNOR_CallbackIDTypeDef CallbackId); +#endif /** * @} - */ + */ /* 6. 导出变量申明 (Exported Variables) --------------------------------- */ /** * @defgroup SFC_exported_var SFC 导出变量申明 (Exported Variables) * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 7. 私有类型定义 (Private Types) -------------------------------------- */ /** * @defgroup SFC_private_types SFC 私有类型定义 (Private Types) * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 8. 私有常量定义Private Constants ------------------------------------- */ /** * @defgroup SFC_private_constants SFC 私有常量定义Private Constants * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 9. 私有宏定义 (Private Macros) -------------------------------------- */ /** * @defgroup SFC_private_macros SFC 私有宏定义 (Private Macros) * @{ */ - -// 删除此行, 添加内容 -// 删除此行, 添加内容 + +#define CONFIG_SPIFLASH_PART_OFFSET 0x5800 + +#define ALIGN(x,a) __ALIGN_MASK((x),(typeof(x))(a)-1) +#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) + +#define __HAL_SFCNOR_WRITE_REG(__HANDLE__, reg, val) WRITE_REG((__HANDLE__)->Instance->reg, val) + +#define __HAL_SFCNOR_CLEAR_ALL_INTC(__HANDLE__) SFCNOR_CLEAR_ALL_INTC((__HANDLE__)->Instance) +#define __HAL_SFCNOR_MASK_ALL_INTC(__HANDLE__) SFCNOR_MASK_ALL_INTC((__HANDLE__)->Instance) +#define __HAL_SFCNOR_MASK_END_INTC(__HANDLE__) SET_BIT((__HANDLE__)->Instance->INTC, SFC_INTC_MASK_END) +#define __HAL_SFCNOR_MASK_TREQ_INTC(__HANDLE__) SET_BIT((__HANDLE__)->Instance->INTC, SFC_INTC_MASK_TREQ) +#define __HAL_SFCNOR_MASK_RREQ_INTC(__HANDLE__) SET_BIT((__HANDLE__)->Instance->INTC, SFC_INTC_MASK_RREQ) +#define __HAL_SFCNOR_MASK_OVER_INTC(__HANDLE__) SET_BIT((__HANDLE__)->Instance->INTC, SFC_INTC_MASK_OVER) +#define __HAL_SFCNOR_MASK_UNDR_INTC(__HANDLE__) SET_BIT((__HANDLE__)->Instance->INTC, SFC_INTC_MASK_UNDR) +#define __HAL_SFCNOR_UNMASK_END_INTC(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->INTC, SFC_INTC_MASK_END) +#define __HAL_SFCNOR_UNMASK_TREQ_INTC(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->INTC, SFC_INTC_MASK_TREQ) +#define __HAL_SFCNOR_UNMASK_RREQ_INTC(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->INTC, SFC_INTC_MASK_RREQ) +#define __HAL_SFCNOR_UNMASK_OVER_INTC(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->INTC, SFC_INTC_MASK_OVER) +#define __HAL_SFCNOR_UNMASK_UNDR_INTC(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->INTC, SFC_INTC_MASK_UNDR) +#define __HAL_SFCNOR_GET_CTL_SR(__HANDLE__) READ_REG((__HANDLE__)->Instance->SR) +#define __HAL_SFCNOR_CLEAR_RREQ(__HANDLE__) WRITE_REG((__HANDLE__)->Instance->SCR, SFC_SCR_CLR_RREQ_0) +#define __HAL_SFCNOR_CLEAR_TREQ(__HANDLE__) WRITE_REG((__HANDLE__)->Instance->SCR, SFC_SCR_CLR_TREQ_0) +#define __HAL_SFCNOR_CLEAR_OVER_INTC(__HANDLE__) WRITE_REG((__HANDLE__)->Instance->SCR, SFC_SCR_CLR_OVER_0) +#define __HAL_SFCNOR_CLEAR_UNDER_INTC(__HANDLE__) WRITE_REG((__HANDLE__)->Instance->SCR, SFC_SCR_CLR_UNDR_0) +#define __HAL_SFCNOR_CLEAR_END_INTC(__HANDLE__) WRITE_REG((__HANDLE__)->Instance->SCR, SFC_SCR_CLR_END_0) +#define __HAL_SFCNOR_GET_DATA(__HANDLE__) READ_REG((__HANDLE__)->Instance->DR); /** * @} - */ + */ /* 10. 私有函数申明 (Private Funcs) ------------------------------------- */ /** * @defgroup SFC_private_funcs SFC 私有函数申明 (Private Funcs) * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 11. 私有变量申明 Private Variables ----------------------------------- */ /** * @defgroup SFC_private_var SFC 私有变量申明 (Private Variables) * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /** * @} - */ + */ /** * @} - */ + */ #ifdef __cplusplus } #endif diff --git a/drivers/drivers-x2600/include/x2600_ll_sfc.h b/drivers/drivers-x2600/include/x2600_ll_sfc.h index eafdaa89..c45bcb6d 100755 --- a/drivers/drivers-x2600/include/x2600_ll_sfc.h +++ b/drivers/drivers-x2600/include/x2600_ll_sfc.h @@ -11,7 +11,7 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ - + #ifndef __X2600_LL_SFC_H__ #define __X2600_LL_SFC_H__ @@ -28,138 +28,430 @@ * @addtogroup g_X2600_SFC_LL_Driver SFC LL 驱动 * @{ */ - + /* 1. 头文件 (Includes)----------------------------------------------- */ -//删除此行,添加内容 -//删除此行,添加内容 +#include "x2600.h" /* 2. 导出的类型 (Exported Types)--------------------------------------- */ /** * @defgroup SFC_exported_types SFC 导出的类型 (Exported Types) * @{ */ - -// 删除此行, 添加内容 -// 删除此行, 添加内容 + +struct spi_nor_cmd_info { + unsigned short cmd; + unsigned char dummy_byte; + unsigned char addr_nbyte; + unsigned char transfer_mode; +}; + +struct spi_nor_st_info { + unsigned short cmd; + unsigned char bit_shift; + unsigned char mask; + unsigned char val; + unsigned char len; /* length of byte to operate from register */ + unsigned char dummy; +}; + +struct spi_nor_info { + unsigned char name[32]; + unsigned int id; + + struct spi_nor_cmd_info read_standard; + struct spi_nor_cmd_info read_quad; + + struct spi_nor_cmd_info write_standard; + struct spi_nor_cmd_info write_quad; + + struct spi_nor_cmd_info sector_erase; + + struct spi_nor_cmd_info wr_en; + struct spi_nor_cmd_info en4byte; + struct spi_nor_st_info quad_set; + struct spi_nor_st_info quad_get; + struct spi_nor_st_info busy; + + unsigned short quad_ops_mode; + unsigned short addr_ops_mode; + + unsigned int tCHSH; /* hold */ + unsigned int tSLCH; /* setup */ + unsigned int tSHSL_RD; /* interval */ + unsigned int tSHSL_WR; + + unsigned int chip_size; + unsigned int page_size; + unsigned int erase_size; + + unsigned char chip_erase_cmd; +}; + +struct nor_partition { + char name[32]; + uint32_t size; + uint32_t offset; + uint32_t mask_flags; /* bit 0-1 mask the partiton RW mode, 0:RW 1:W 2:R */ + uint32_t manager_mode; +}; + +struct norflash_partitions { + struct nor_partition nor_partition[10]; + uint32_t num_partition_info; +}; + +struct burner_params { + uint32_t magic; + uint32_t version; + struct spi_nor_info spi_nor_info; + struct norflash_partitions norflash_partitions; + unsigned int fs_erase_size; + unsigned char uk_quad; /* for uboot kernel set quad mode */ +}; + +typedef struct { + unsigned int NextDesAddr; + unsigned int MemAddr; + unsigned int TranLen; + unsigned int Link; +} SFCNOR_DMA_Descriptor; + +typedef struct { + + uint32_t datalen; + uint32_t cur_len; + uint8_t data_dir; + uint8_t ops_mode; + uint8_t *buf; +} data_config; + +struct sfc_cdt_xfer { + + unsigned short cmd_index; + uint8_t dataen; + + data_config config; + uint32_t dmaDescAddr; + uint32_t columnaddr; + uint32_t rowaddr; + uint32_t staaddr0; + uint32_t staaddr1; +}; + +/* SFC CDT INDEX */ +enum { + /* 1. nor reset */ + NOR_RESET_ENABLE, + NOR_RESET, + + /* 2. nor read id */ + NOR_READ_ID, + + /* 3. nor get status */ + NOR_GET_STATUS, + NOR_GET_STATUS_1, + NOR_GET_STATUS_2, + + /* 4. nor singleRead */ + NOR_READ_STANDARD, + + /* 5. nor quadRead */ + NOR_READ_QUAD, + + /* 6. nor writeStandard */ + NOR_WRITE_STANDARD_ENABLE, + NOR_WRITE_STANDARD, + NOR_WRITE_STANDARD_FINISH, + + /* 7. nor writeQuad */ + NOR_WRITE_QUAD_ENABLE, + NOR_WRITE_QUAD, + NOR_WRITE_QUAD_FINISH, + + /* 8. nor erase */ + NOR_ERASE_WRITE_ENABLE, + NOR_ERASE, + NOR_ERASE_FINISH, + + /* 9. quad mode */ + NOR_QUAD_SET_ENABLE, + NOR_QUAD_SET, + NOR_QUAD_FINISH, + NOR_QUAD_GET, + + /* 10. nor write ENABLE */ + NOR_WRITE_ENABLE, + + /* 11. entry 4byte mode */ + NOR_EN_4BYTE, + + /* 12. chip erase */ + NOR_CHIP_ERASE_WRITE_ENABLE, + NOR_CHIP_ERASE, + NOR_CHIP_ERASE_FINISH, + + /* 13. active die */ + NOR_DIE_SELECT, + + /* 14. read die id */ + NOR_READ_ACTIVE_DIE_ID, + + /* index count */ + NOR_MAX_INDEX, +}; +enum { + COL_ADDR, + ROW_ADDR, + STA_ADDR0, + STA_ADDR1, +}; + +struct sfc_cdt { + uint32_t link; + uint32_t xfer; + uint32_t staExp; + uint32_t staMsk; +}; + +typedef enum { + POLL_MODE = 0x00U, + IT_MODE = 0x01U, + DMA_POLL_MODE = 0x02U, + DMA_IT_MODE = 0x04U +} OperationMode; /** * @} - */ + */ /* 3. 导出常量定义 Exported Constants ----------------------------------- */ /** * @defgroup SFC_exported_constants SFC 导出的常量 Exported Constants * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 4. 导出宏定义 Exported Macros --------------------------------------- */ /** * @defgroup SFC_exported_macros SFC 导出宏 Exported Macros * @{ */ - -// 删除此行, 添加内容 -// 删除此行, 添加内容 + +#define __HAL_SFCNOR_CMD_XFER(ADDR_WIDTH, POLL_EN, DMY_BITS, DATA_EN, CMD) ( \ + (ADDR_WIDTH << SFC_TRAN_CFG0n_ADDR_WIDTH_Pos) \ + | (POLL_EN << SFC_TRAN_CFG0n_POLL_EN_Pos) \ + | (SFC_TRAN_CFG0n_CMD_EN_0) \ + | (0 << SFC_TRAN_CFG0n_PHASE_FORMAT_Pos) \ + | (DMY_BITS << SFC_TRAN_CFG0n_DMY_BITS_Pos) \ + | (DATA_EN << SFC_TRAN_CFG0n_DATE_EN_Pos) \ + | CMD \ + ) + +#define __HAL_SFCNOR_CMD_LINK(LINK, ADDRMODE, TRAN_MODE) ( \ + (LINK << 31) | (TRAN_MODE << SFC_TRAN_CFG1n_TRAN_MD_Pos) | (ADDRMODE) \ + ) + +#define SFCNOR_SET_CPU_MODE(__SFCNORx__) CLEAR_BIT((__SFCNORx__)->GLB0, SFC_GLB0_OP_MODE) +#define SFCNOR_SET_DMA_MODE(__SFCNORx__) SET_BIT((__SFCNORx__)->GLB0, SFC_GLB0_OP_MODE) +#define SFCNOR_SET_DESC_ADDR(__SFCNORx__, val) WRITE_REG((__SFCNORx__)->DES_ADDR, val) +#define SFCNOR_SET_CDT_ENABLE(__SFCNORx__) SET_BIT((__SFCNORx__)->GLB0, SFC_GLB0_CDT_EN) +#define SFCNOR_SET_FLASH_TIMING(__SFCNORx__,val) WRITE_REG((__SFCNORx__)->DEV_CONF, val) +#define SFCNOR_SET_SMP_DELAY(__SFCNORx__, val) MODIFY_REG((__SFCNORx__)->DEV_CONF, SFC_DEV_CONF_SMP_DELAY_Msk, val) + +#define SFCNOR_CLEAR_ALL_INTC(__SFCNORx__) WRITE_REG((__SFCNORx__)->SCR, 0x1f) +#define SFCNOR_MASK_ALL_INTC(__SFCNORx__) WRITE_REG((__SFCNORx__)->INTC, 0x1f) +#define SFCNOR_ENABLE_ALL_INTC(__SFCNORx__) WRITE_REG((__SFCNORx__)->INTC, 0) +#define SFCNOR_TRIG_FLUSH(__SFCNORx__) SET_BIT((__SFCNORx__)->TRIG, SFC_TRIG_FLUSH_0) +#define SFCNOR_TRIG_START(__SFCNORx__) WRITE_REG((__SFCNORx__)->TRIG, SFC_TRIG_START_0) +#define SFCNOR_TRIG_STOP(__SFCNORx__) \ + do { \ + int32_t timeout = 0xffff; \ + WRITE_REG((__SFCNORx__)->TRIG, SFC_TRIG_STOP_0); \ + while((READ_BIT(__SFCNORx__->SR, SFC_SR_BUSY_Msk)) && timeout--); \ + } while (0) +#define SFCNOR_TRIG_SET_STOP(__SFCNORx__) SET_BIT((__SFCNORx__)->TRIG, SFC_TRIG_STOP) +#define SFCNOR_SET_HOLD(__SFCNORx__) SET_BIT((__SFCNORx__)->DEV_CONF, SFC_DEV_CONF_HOLD_DL) +#define SFCNOR_SET_WP(__SFCNORx__) SET_BIT((__SFCNORx__)->DEV_CONF, SFC_DEV_CONF_WP_DL) +#define SFCNOR_SET_CLOCK_PHASE(__SFCNORx__, val) \ + if(val == 0) \ + CLEAR_BIT((__SFCNORx__)->DEV_CONF, SFC_DEV_CONF_CPHA); \ + else \ + SET_BIT((__SFCNORx__)->DEV_CONF, SFC_DEV_CONF_CPHA) +#define SFCNOR_SET_CLOCK_POLARITY(__SFCNORx__, val) \ + if(val == 0) \ + CLEAR_BIT((__SFCNORx__)->DEV_CONF, SFC_DEV_CONF_CPOL); \ + else \ + SET_BIT((__SFCNORx__)->DEV_CONF, SFC_DEV_CONF_CPOL) +#define SFCNOR_SET_CE(__SFCNORx__, val) \ + if(val == 0) \ + CLEAR_BIT((__SFCNORx__)->DEV_CONF, SFC_DEV_CONF_CE_DL); \ + else \ + SET_BIT((__SFCNORx__)->DEV_CONF, SFC_DEV_CONF_CE_DL) +#define SFCNOR_SET_TRANSFER_MODE(__SFCNORx__, val) \ + if(val == 0) \ + CLEAR_BIT((__SFCNORx__)->GLB0, SFC_GLB0_OP_MODE); \ + else \ + SET_BIT((__SFCNORx__)->GLB0, SFC_GLB0_OP_MODE) +#define SFCNOR_SET_DES_EN(__SFCNORx__, val) \ + if(val == 0) \ + CLEAR_BIT((__SFCNORx__)->GLB0, SFC_GLB0_DES_EN); \ + else \ + SET_BIT((__SFCNORx__)->GLB0, SFC_GLB0_DES_EN) /** * @} - */ + */ /* 5. 导出函数申明 Exported Funcs --------------------------------------- */ /** * @defgroup SFC_exported_funcs SFC 导出函数申明 Exported Funcs * @{ */ - -// 删除此行, 添加内容 -// 删除此行, 添加内容 +void SFCNOR_DumpReg(SFC_TypeDef *SFCNORx); +void SFCNOR_DumpCdt(SFC_TypeDef *SFCNORx); +void SFCNOR_DumpInfo(SFC_TypeDef *SFCNORx); +void SFCNOR_DumpClonerParams(struct spi_nor_info *spi_nor_info); +void SFCNOR_memcpy(void *dst, void *src, unsigned int count); +void SFCNOR_CreateCdtTable_First(SFC_TypeDef *SFCNORx); +void SFCNOR_CreateCdtTable_Second(SFC_TypeDef *SFCNORx, struct spi_nor_info *params); +void SFCNOR_CdtXferInitParams(struct sfc_cdt_xfer *xfer); +void SFCNOR_RegInit(SFC_TypeDef *SFCNORx); +void SFCNOR_CtlInit(SFC_TypeDef *SFCNORx, OperationMode in_mode); +void SFCNOR_SyncCdt(SFC_TypeDef *SFCNORx, struct sfc_cdt_xfer *xfer, int itmode); /** * @} - */ + */ /* 6. 导出变量申明 (Exported Variables) --------------------------------- */ /** * @defgroup SFC_exported_var SFC 导出变量申明 (Exported Variables) * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 7. 私有类型定义 (Private Types) -------------------------------------- */ /** * @defgroup SFC_private_types SFC 私有类型定义 (Private Types) * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 8. 私有常量定义Private Constants ------------------------------------- */ /** * @defgroup SFC_private_constants SFC 私有常量定义Private Constants * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 9. 私有宏定义 (Private Macros) -------------------------------------- */ /** * @defgroup SFC_private_macros SFC 私有宏定义 (Private Macros) * @{ */ - -// 删除此行, 添加内容 -// 删除此行, 添加内容 + +#define THRESHOLD 32 +#define DEF_TIM_VAL 0x00000087 //generated by sfc_timing_params + +#define ENABLE 1 +#define DISABLE 0 + +#define COM_CMD 1 // common cmd +#define POLL_CMD 2 // the cmd will poll the status of flash,ext: read status + +#define DMA_OPS 1 +#define CPU_OPS 0 + +#define TM_STD_SPI 0 +#define TM_DI_DO_SPI 1 +#define TM_DIO_SPI 2 +#define TM_FULL_DIO_SPI 3 +#define TM_QI_QO_SPI 5 +#define TM_QIO_SPI 6 +#define TM_FULL_QIO_SPI 7 +#define TM_OCTAL_SPT 9 +#define TM_OCTAL_IO_SPI 10 +#define TM_OCTAL_FULL_SPI 11 + +#define DEFAULT_ADDRSIZE 3 +#define DEFAULT_ADDRMODE 0 + +/* nor flash cmd */ +#define SPINOR_OP_RSTEN 0x66 /* reset enable */ +#define SPINOR_OP_RST 0x99 /* reset */ +#define SPINOR_OP_RDID 0x9f /* Read JEDEC ID */ +#define SPINOR_OP_RDSR 0x05 /* Read status register */ +#define SPINOR_OP_RDSR_1 0x35 /* Read status1 register */ +#define SPINOR_OP_RDSR_2 0x15 /* Read status2 register */ +#define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */ + +#define GLB_TRAN_DIR_WRITE 1 +#define GLB_TRAN_DIR_READ 0 + +#define IS_SFCNOR_INSTANCE(__INSTANCE__) ((__INSTANCE__) == SFC_Instance) +#define IS_SFCNOR_MODE(MODE) ((MODE == POLL_MODE) || \ + (MODE == IT_MODE) || \ + (MODE == DMA_POLL_MODE) || \ + (MODE == DMA_IT_MODE)) + +#define IS_SFCNOR_CMD_INDEX(INDEX) ((INDEX) < NOR_MAX_INDEX) +#define IS_SFCNOR_DATAEN(val) ((val == ENABLE) || (val == DISABLE)) +#define IS_SFCNOR_DATA_DIR(val) ((val == GLB_TRAN_DIR_READ) || (val == GLB_TRAN_DIR_WRITE)) +#define IS_SFCNOR_OPS_MODE(MODE) ((MODE == CPU_OPS) || (MODE == DMA_OPS)) +#define IS_SFCNOR_DATALEN(val) ((val != 0)) +#define IS_SFCNOR_ITMODE(val) ((val == 0) || (val == 1)) /** * @} - */ + */ /* 10. 私有函数申明 (Private Funcs) ------------------------------------- */ /** * @defgroup SFC_private_funcs SFC 私有函数申明 (Private Funcs) * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 11. 私有变量申明 Private Variables ----------------------------------- */ /** * @defgroup SFC_private_var SFC 私有变量申明 (Private Variables) * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /** * @} - */ + */ /** * @} - */ + */ #ifdef __cplusplus } #endif diff --git a/drivers/drivers-x2600/src/x2600_hal_sfc.c b/drivers/drivers-x2600/src/x2600_hal_sfc.c index 398ff449..c05b928e 100755 --- a/drivers/drivers-x2600/src/x2600_hal_sfc.c +++ b/drivers/drivers-x2600/src/x2600_hal_sfc.c @@ -17,98 +17,1378 @@ [!!!!删除此内容,添加针对模块的使用方法说明,例如: 配置,启动/停止,状态,重点提醒等等.!!!!] @endverbatim */ - + /* 1.头文件 (Includes)------------------------------------------------ */ +#include "x2600_hal.h" /** @addtogroup g_X2600_SFC_HAL_Driver * @{ */ - + /* 2.私有常量定义Private Constants -------------------------------------- */ /** - * @addtogroup SFC_private_constants + * @addtogroup SFC_private_constants * @{ */ - -// 删除此行, 添加内容 -// 删除此行, 添加内容 + +/** + * @brief DMA Descriptor 使用的数据空间 + */ +static SFCNOR_DMA_Descriptor ALIGN_32BYTES(DMA_DESC_SPACE); +SFCNOR_DMA_Descriptor *pDmaDesc; /** * @} - */ + */ /* 3. 私有类型定义 (Private Types) -------------------------------------- */ /** - * @addtogroup SFC_private_types + * @addtogroup SFC_private_types * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 4. 私有宏定义 (Private Macros) -------------------------------------- */ /** - * @addtogroup SFC_private_macros + * @addtogroup SFC_private_macros * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 5. 私有变量申明 Private Variables ------------------------------------ */ /** - * @addtogroup SFC_private_var + * @addtogroup SFC_private_var * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 6. 私有函数申明 (Private Funcs) -------------------------------------- */ /** - * @addtogroup SFC_private_funcs + * @addtogroup SFC_private_funcs * @{ */ - -// 删除此行, 添加内容 -// 删除此行, 添加内容 + +static unsigned int SFCNOR_Write(SFCNOR_HandleTypeDef *hnor, uint32_t addr, uint32_t len, uint8_t *buf); +static int SFCNOR_EraseBlock(SFCNOR_HandleTypeDef *hnor, uint32_t addr); /** * @} - */ + */ /* 7. 私有函数实现 (Private Funcs) -------------------------------------- */ /** * @defgroup SFC_private_funcs_impl SFC 私有函数实现 * @{ */ - -// 删除此行, 添加内容 -// 删除此行, 添加内容 + +/** + * @brief write data to sfc register in cpu polling mode + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param xfer sfc cdt configure value + * @retval None + */ +static unsigned int SFCNOR_CpuWriteTxFifo(SFCNOR_HandleTypeDef *hnor, struct sfc_cdt_xfer *xfer) +{ + int i; + unsigned long align_len = 0; + unsigned int fifo_num = 0; + + align_len = ALIGN(xfer->config.datalen, 4); + + if (((align_len - xfer->config.cur_len) / 4) > THRESHOLD) { + fifo_num = THRESHOLD; + } else { + fifo_num = (align_len - xfer->config.cur_len) / 4; + } + + for (i = 0; i < fifo_num; i++) { + __HAL_SFCNOR_WRITE_REG(hnor, DR, *(unsigned int *)xfer->config.buf); + xfer->config.buf += 4; + xfer->config.cur_len += 4; + } + + return 0; +} + +/** + * @brief get data in cpu polling mode + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param xfer sfc cdt configure value + * @retval None + */ +static unsigned int SFCNOR_CpuReadRxFifo(SFCNOR_HandleTypeDef *hnor, struct sfc_cdt_xfer *xfer) +{ + int i; + unsigned long align_len = 0; + unsigned int fifo_num = 0; + + align_len = ALIGN(xfer->config.datalen, 4); + + if (((align_len - xfer->config.cur_len) / 4) > THRESHOLD) { + fifo_num = THRESHOLD; + } else { + fifo_num = (align_len - xfer->config.cur_len) / 4; + } + + for (i = 0; i < fifo_num; i++) { + *(unsigned int *)xfer->config.buf = __HAL_SFCNOR_GET_DATA(hnor); + xfer->config.buf += 4; + xfer->config.cur_len += 4; + } + + return 0; +} + +/** + * @brief polling wait data transfer + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param xfer sfc cdt configure value + * @retval None + */ +static void SFCNOR_SrHandle(SFCNOR_HandleTypeDef *hnor, struct sfc_cdt_xfer *xfer) +{ + unsigned int reg_sr = 0; + unsigned int tmp = 0; + while (1) { + reg_sr = __HAL_SFCNOR_GET_CTL_SR(hnor); + + if (reg_sr & SFC_SR_END) { + tmp = SFC_SCR_CLR_END_0; + break; + } + + if (reg_sr & SFC_SR_RECE_REQ) { + __HAL_SFCNOR_CLEAR_RREQ(hnor); + SFCNOR_CpuReadRxFifo(hnor, xfer); + } + + if (reg_sr & SFC_SR_TRAN_REQ) { + __HAL_SFCNOR_CLEAR_TREQ(hnor); + SFCNOR_CpuWriteTxFifo(hnor, xfer); + } + + if (reg_sr & SFC_SR_UNDER) { + tmp = SFC_SCR_CLR_UNDR_0; + prom_printk("UNDR!\n"); + break; + } + + if (reg_sr & SFC_SR_OVER) { + tmp = SFC_SCR_CLR_OVER_0; + prom_printk("OVER!\n"); + break; + } + } + if (tmp) { + __HAL_SFCNOR_WRITE_REG(hnor, SCR, tmp); + } +} + +/** + * @brief read data from fifo in cpu interrupt mode + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval None + */ +static void SFCNOR_CpuReadRxFifo_IT(SFCNOR_HandleTypeDef *hnor) +{ + struct sfc_cdt_xfer *xfer = &hnor->xfer; + int32_t i = 0; + uint32_t align_len = 0; + uint32_t fifo_num = 0; + uint32_t last_word = 0; + uint32_t unalign_data; + uint8_t *c; + + align_len = ALIGN(xfer->config.datalen, 4); + + if (((align_len - xfer->config.cur_len) / 4) > THRESHOLD) { + fifo_num = THRESHOLD; + last_word = 0; + } else { + /* last aligned THRESHOLD data*/ + if (xfer->config.datalen % 4) { + fifo_num = (align_len - xfer->config.cur_len) / 4 - 1; + last_word = 1; + } else { + fifo_num = (align_len - xfer->config.cur_len) / 4; + last_word = 0; + } + } + + if ((uint32_t)xfer->config.buf & 0x3) { + /* addr not align */ + for (i = 0; i < fifo_num; i++) { + unalign_data = __HAL_SFCNOR_GET_DATA(hnor); + c = xfer->config.buf; + c[0] = (unalign_data >> 0) & 0xff; + c[1] = (unalign_data >> 8) & 0xff; + c[2] = (unalign_data >> 16) & 0xff; + c[3] = (unalign_data >> 24) & 0xff; + + xfer->config.buf += 4; + xfer->config.cur_len += 4; + } + } else { + /* addr align */ + for (i = 0; i < fifo_num; i++) { + *(uint32_t *)xfer->config.buf = __HAL_SFCNOR_GET_DATA(hnor); + xfer->config.buf += 4; + xfer->config.cur_len += 4; + } + } + + /* last word */ + if (last_word == 1) { + unalign_data = __HAL_SFCNOR_GET_DATA(hnor); + c = (uint8_t *)xfer->config.buf; + + for (i = 0; i < xfer->config.datalen % 4; i++) { + c[i] = (unalign_data >> (i * 8)) & 0xff; + } + + xfer->config.buf += xfer->config.datalen % 4; + xfer->config.cur_len += xfer->config.datalen % 4; + } +} + +/** + * @brief write data to fifo in cpu interrupt mode + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval None + */ +static void SFCNOR_CpuWriteTxFifo_IT(SFCNOR_HandleTypeDef *hnor) +{ + struct sfc_cdt_xfer *xfer = &hnor->xfer; + uint32_t align_len = 0; + uint32_t fifo_num = 0; + uint32_t data = 0; + uint32_t i; + uint32_t nbytes = xfer->config.datalen % 4; + + align_len = xfer->config.datalen / 4 * 4; + + if (((align_len - xfer->config.cur_len) / 4) >= THRESHOLD) { + fifo_num = THRESHOLD; + nbytes = 0; + } else { + fifo_num = (align_len - xfer->config.cur_len) / 4; + } + + if ((uint32_t)xfer->config.buf & 0x3) { + /* addr not align */ + for (i = 0; i < fifo_num; i++) { + data = xfer->config.buf[3] << 24 | xfer->config.buf[2] << 16 | xfer->config.buf[1] << 8 | xfer->config.buf[0]; + __HAL_SFCNOR_WRITE_REG(hnor, DR, data); + xfer->config.buf += 4; + xfer->config.cur_len += 4; + } + } else { + /* addr align */ + for (i = 0; i < fifo_num; i++) { + __HAL_SFCNOR_WRITE_REG(hnor, DR, *(uint32_t *)xfer->config.buf); + xfer->config.buf += 4; + xfer->config.cur_len += 4; + } + } + + if (nbytes) { + data = 0; + for (i = 0; i < nbytes; i++) { + data |= xfer->config.buf[i] << i * 8; + } + __HAL_SFCNOR_WRITE_REG(hnor, DR, data); + xfer->config.cur_len += nbytes; + } +} + +/** + * @brief reset SFCNOR flash + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval None + */ +static void SFCNOR_Reset(SFCNOR_HandleTypeDef *hnor) +{ + struct sfc_cdt_xfer *xfer = &hnor->xfer; + SFCNOR_CdtXferInitParams(xfer); + + /* set Index */ + xfer->cmd_index = NOR_RESET_ENABLE; + + /* set addr */ + xfer->rowaddr = 0; + xfer->columnaddr = 0; + + /* set transfer config */ + xfer->dataen = DISABLE; + + /* use polling mode */ + SFCNOR_SyncCdt(hnor->Instance, xfer, 0); + SFCNOR_SrHandle(hnor, xfer); + + HAL_Delay(1U); +} + +/** + * @brief Read flash parameter + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param addr pointer to Device address storage flash parameter + * @param len read data length + * @param buf pointer to buffer storage flash parameter + * @retval None + */ +static void SFCNOR_ReadParams(SFCNOR_HandleTypeDef *hnor, unsigned int addr, unsigned char *buf, unsigned int len) +{ + struct sfc_cdt_xfer *xfer = &hnor->xfer; + SFCNOR_CdtXferInitParams(xfer); + + xfer->cmd_index = NOR_READ_STANDARD; + + /* set addr */ + xfer->columnaddr = 0; + xfer->rowaddr = addr; + + /* set transfer config */ + xfer->dataen = ENABLE; + xfer->config.datalen = len; + xfer->config.data_dir = GLB_TRAN_DIR_READ; + xfer->config.ops_mode = CPU_OPS; + xfer->config.buf = buf; + + /* use polling mode */ + SFCNOR_SyncCdt(hnor->Instance, xfer, 0); + SFCNOR_SrHandle(hnor, xfer); +} + +/** + * @brief write nor flash status register QE bit to set quad mode + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval None + */ +static void SFCNOR_SetQuadModeReg(SFCNOR_HandleTypeDef *hnor) +{ + struct spi_nor_st_info *quad_set; + struct spi_nor_info *spi_nor_info = &hnor->spi_nor_info; + + struct sfc_cdt_xfer *xfer = &hnor->xfer; + unsigned int data; + + quad_set = &spi_nor_info->quad_set; + data = (quad_set->val & quad_set->mask) << quad_set->bit_shift; + + SFCNOR_CdtXferInitParams(xfer); + /* set index */ + xfer->cmd_index = NOR_QUAD_SET_ENABLE; + + /* set addr */ + xfer->columnaddr = 0; + xfer->rowaddr = 0; + + /* set transfer config */ + xfer->dataen = ENABLE; + xfer->config.datalen = quad_set->len; + xfer->config.data_dir = GLB_TRAN_DIR_WRITE; + xfer->config.ops_mode = CPU_OPS; + xfer->config.buf = (uint8_t *)&data; + + /* use polling mode */ + SFCNOR_SyncCdt(hnor->Instance, xfer, 0); + SFCNOR_SrHandle(hnor, xfer); + +} + +/** + * @brief set SFCNOR memory Enter4Byte + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval None + */ +static void SFCNOR_Enter4Byte(SFCNOR_HandleTypeDef *hnor) +{ + struct sfc_cdt_xfer *xfer = &hnor->xfer; + SFCNOR_CdtXferInitParams(xfer); + + /* set index */ + xfer->cmd_index = NOR_EN_4BYTE; + + /* set addr */ + xfer->columnaddr = 0; + + /* set transfer config */ + xfer->dataen = DISABLE; + + /* use polling mode */ + SFCNOR_SyncCdt(hnor->Instance, xfer, 0); + SFCNOR_SrHandle(hnor, xfer); +} + +/** + * @brief set SFCNOR memory Write enable + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval None + */ +static void SFCNOR_WriteEnable(SFCNOR_HandleTypeDef *hnor) +{ + struct sfc_cdt_xfer *xfer = &hnor->xfer; + SFCNOR_CdtXferInitParams(xfer); + + /* set index */ + xfer->cmd_index = NOR_WRITE_ENABLE; + + /* set addr */ + xfer->columnaddr = 0; + + /* set transfer config */ + xfer->dataen = DISABLE; + + /* use polling mode */ + SFCNOR_SyncCdt(hnor->Instance, xfer, 0); + SFCNOR_SrHandle(hnor, xfer); +} + +/** + * @brief Read data from NOR memory + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param addr pointer to Device address + * @param len read data len + * @param buf pointer to read data buffer + * @retval read len + */ +static unsigned int SFCNOR_Read(SFCNOR_HandleTypeDef *hnor, uint32_t addr, uint8_t *buf, uint32_t len) +{ + struct sfc_cdt_xfer *xfer = &hnor->xfer; + SFCNOR_CdtXferInitParams(xfer); + + /* set Index */ + if (hnor->quad_succeed) { + xfer->cmd_index = NOR_READ_QUAD; + } else { + xfer->cmd_index = NOR_READ_STANDARD; + } + + /* set addr */ + xfer->columnaddr = 0; + xfer->rowaddr = addr; + + /* set transfer config */ + xfer->dataen = ENABLE; + xfer->config.datalen = len; + xfer->config.data_dir = GLB_TRAN_DIR_READ; + if ((hnor->in_mode == DMA_IT_MODE) || (hnor->in_mode == DMA_POLL_MODE)) { + pDmaDesc->NextDesAddr = 0; + pDmaDesc->MemAddr = (uint32_t)CPHYSADDR(buf); + pDmaDesc->TranLen = len; + pDmaDesc->Link = 0; + xfer->dmaDescAddr = (uint32_t)CPHYSADDR(pDmaDesc); + xfer->config.ops_mode = DMA_OPS; + } else { + xfer->config.ops_mode = CPU_OPS; + } + xfer->config.buf = (uint8_t *)buf; + + if ((hnor->in_mode == IT_MODE) || (hnor->in_mode == DMA_IT_MODE)) { + SFCNOR_SyncCdt(hnor->Instance, xfer, 1); + } else { + SFCNOR_SyncCdt(hnor->Instance, xfer, 0); + SFCNOR_SrHandle(hnor, xfer); + } + return len; +} + +/** + * @brief Program data in one page to SFCNOR memory + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param addr Device address + * @param len Program len + * @retval write len + */ +static unsigned int SFCNOR_Write(SFCNOR_HandleTypeDef *hnor, uint32_t addr, uint32_t len, uint8_t *buf) +{ + struct sfc_cdt_xfer *xfer = &hnor->xfer; + SFCNOR_CdtXferInitParams(xfer); + + /* set Index */ + if (hnor->quad_succeed) { + xfer->cmd_index = NOR_WRITE_QUAD_ENABLE; + } else { + xfer->cmd_index = NOR_WRITE_STANDARD_ENABLE; + } + + /* set addr */ + xfer->columnaddr = 0; + xfer->rowaddr = addr; + + /* set transfer config */ + xfer->dataen = ENABLE; + xfer->config.datalen = len; + xfer->config.data_dir = GLB_TRAN_DIR_WRITE; + if ((hnor->in_mode == DMA_IT_MODE) || (hnor->in_mode == DMA_POLL_MODE)) { + pDmaDesc->NextDesAddr = 0; + pDmaDesc->MemAddr = (uint32_t)CPHYSADDR(buf); + pDmaDesc->TranLen = len; + pDmaDesc->Link = 0; + xfer->dmaDescAddr = (uint32_t)CPHYSADDR(pDmaDesc); + xfer->config.ops_mode = DMA_OPS; + } else { + xfer->config.ops_mode = CPU_OPS; + } + xfer->config.buf = (uint8_t *)buf; + + if ((hnor->in_mode == IT_MODE) || (hnor->in_mode == DMA_IT_MODE)) { + hnor->pTxAddress += len; + hnor->pTxBuffPtr += len; + hnor->TxXferSize -= len; + /* use interrupt mode */ + SFCNOR_SyncCdt(hnor->Instance, xfer, 1); + } else { + /* use polling mode */ + SFCNOR_SyncCdt(hnor->Instance, xfer, 0); + SFCNOR_SrHandle(hnor, xfer); + } + + return len; +} + +/** + * @brief Erase the specified block of the SFCNOR memory + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param addr:Block to erase address + * @retval erase status + */ +static int SFCNOR_EraseBlock(SFCNOR_HandleTypeDef *hnor, uint32_t addr) +{ + struct sfc_cdt_xfer *xfer = &hnor->xfer; + struct spi_nor_info *spi_nor_info = &hnor->spi_nor_info; + int erasesize = spi_nor_info->erase_size; + + SFCNOR_CdtXferInitParams(xfer); + + /* set Index */ + xfer->cmd_index = NOR_ERASE_WRITE_ENABLE; + + /* set addr */ + xfer->rowaddr = addr; + + /* set transfer config */ + xfer->dataen = DISABLE; + + if ((hnor->in_mode == IT_MODE) || (hnor->in_mode == DMA_IT_MODE)) { + /* use interrupt mode */ + hnor->pEAddress += erasesize; + hnor->Elen -= erasesize; + SFCNOR_SyncCdt(hnor->Instance, xfer, 1); + } else { + /* use polling mode */ + SFCNOR_SyncCdt(hnor->Instance, xfer, 0); + SFCNOR_SrHandle(hnor, xfer); + } + + return 0; + +} + +/** + * @brief Perform the NOR memory Initialization sequence + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval HAL status + */ +HAL_StatusTypeDef SFCNOR_Init(SFCNOR_HandleTypeDef *hnor) +{ + if (hnor == NULL) { + return HAL_ERROR; + } + + if (hnor->State == HAL_SFCNOR_STATE_RESET) { +#if (USE_HAL_SFCNOR_REGISTER_CALLBACKS == 1) + hnor->EraseFinishCallback = HAL_SFCNOR_EraseFinishCallback; + hnor->WriteFinishCallback = HAL_SFCNOR_WriteFinishCallback; + hnor->ReadFinishCallback = HAL_SFCNOR_ReadFinishCallback; + hnor->ErrorCallback = HAL_SFCNOR_ErrorCallback; + if (hnor->MspInitCallback == NULL) { + hnor->MspInitCallback = HAL_SFCNOR_MspInit; + } + + /* Init the low level hardware */ + hnor->MspInitCallback(hnor); +#else + /* Initialize the low level hardware (MSP) */ + HAL_SFCNOR_MspInit(hnor); +#endif /* (USE_HAL_SFCNOR_REGISTER_CALLBACKS) */ + } + + assert_param(IS_SFCNOR_INSTANCE(hnor->Instance)); + + SFCNOR_CtlInit(hnor->Instance, hnor->in_mode); + SFCNOR_CreateCdtTable_First(hnor->Instance); + /* reset nor flash */ + SFCNOR_Reset(hnor); + /* get nor flash params */ + struct burner_params burner_params; + SFCNOR_ReadParams(hnor, CONFIG_SPIFLASH_PART_OFFSET, (unsigned char *)&burner_params, sizeof(struct burner_params)); + SFCNOR_memcpy(&hnor->spi_nor_info, &burner_params.spi_nor_info, sizeof(struct spi_nor_info)); + prom_printk("hnor->spi_nor_info.name:%s, hnor->spi_nor_info.id=%x\n", hnor->spi_nor_info.name, hnor->spi_nor_info.id); + SFCNOR_memcpy(&hnor->norflash_partitions, &burner_params.norflash_partitions, sizeof(struct norflash_partitions)); + //SFCNOR_DumpClonerParams(&hnor->spi_nor_info); + + SFCNOR_CreateCdtTable_Second(hnor->Instance, &hnor->spi_nor_info); + //SFCNOR_DumpCdt(hnor->Instance); + if (hnor->spi_nor_info.quad_ops_mode == 1) { + SFCNOR_SetQuadModeReg(hnor); + hnor->quad_succeed = 1; + } else { + hnor->quad_succeed = 0; + } + if (hnor->spi_nor_info.chip_size > 0x1000000) { + switch (hnor->spi_nor_info.addr_ops_mode) { + case 0: + SFCNOR_Enter4Byte(hnor); + break; + case 1: + SFCNOR_WriteEnable(hnor); + SFCNOR_Enter4Byte(hnor); + break; + default: + break; + } + } + DMA_DESC_SPACE.NextDesAddr = 0; + CleanInvalidateDCache_by_Addr((uint32_t *)&DMA_DESC_SPACE, sizeof(DMA_DESC_SPACE)); + pDmaDesc = (SFCNOR_DMA_Descriptor *)CKSEG1ADDR((uint32_t)&DMA_DESC_SPACE); + + /* Check the NOR controller state */ + hnor->State = HAL_SFCNOR_STATE_READY; + + return HAL_OK; +} /** * @} - */ + */ /* 8. 导出函数实现------------------------------------------------------- */ /** * @defgroup SFC_exported_funcs_impl SFC 导出函数实现 * @{ */ - -// 删除此行, 添加内容 -// 删除此行, 添加内容 + +/** + * @brief This function handles SFCNOR interrupt request. + * @param irq: irq + * @param data: Pointer to SFCNOR handle + * @retval None + */ +void HAL_SFCNOR_IRQHandler(int irq, void *data) +{ + SFCNOR_HandleTypeDef *hnor = (SFCNOR_HandleTypeDef *)data; + uint32_t val; + uint8_t err_flag = 0; + + val = __HAL_SFCNOR_GET_CTL_SR(hnor) & 0x1f; + //prom_printk("%s:%d:val = %08x\n",__func__,__LINE__,val); + + if (val & SFC_SR_RECE_REQ) { + __HAL_SFCNOR_CLEAR_RREQ(hnor); + SFCNOR_CpuReadRxFifo_IT(hnor); + } else if (val & SFC_SR_TRAN_REQ) { + __HAL_SFCNOR_CLEAR_TREQ(hnor); + SFCNOR_CpuWriteTxFifo_IT(hnor); + } else if (val & SFC_SR_OVER) { + __HAL_SFCNOR_CLEAR_OVER_INTC(hnor); + prom_printk("sfc OVER !\n"); + err_flag = 1; + } else if (val & SFC_SR_UNDER) { + __HAL_SFCNOR_CLEAR_UNDER_INTC(hnor); + prom_printk("sfc UNDR !\n"); + err_flag = 1; + } else if (val & SFC_SR_END) { + __HAL_SFCNOR_MASK_ALL_INTC(hnor); + __HAL_SFCNOR_CLEAR_END_INTC(hnor); + + if ((hnor->xfer.cmd_index == NOR_WRITE_QUAD_ENABLE) || (hnor->xfer.cmd_index == NOR_WRITE_STANDARD_ENABLE)) { + if (hnor->TxXferSize) { + if (hnor->TxXferSize >= hnor->spi_nor_info.page_size) { + SFCNOR_Write(hnor, hnor->pTxAddress, hnor->spi_nor_info.page_size, hnor->pTxBuffPtr); + } else { + SFCNOR_Write(hnor, hnor->pTxAddress, hnor->TxXferSize, hnor->pTxBuffPtr); + } + } else { + HAL_SFCNOR_WriteFinishCallback(hnor); + + /* Check the NOR controller state */ + hnor->State = HAL_SFCNOR_STATE_READY; + } + } + if ((hnor->xfer.cmd_index == NOR_READ_QUAD) || (hnor->xfer.cmd_index == NOR_READ_STANDARD)) { + HAL_SFCNOR_ReadFinishCallback(hnor); + + /* Check the NOR controller state */ + hnor->State = HAL_SFCNOR_STATE_READY; + } + if (hnor->xfer.cmd_index == NOR_ERASE_WRITE_ENABLE) { + if (hnor->Elen) { + SFCNOR_EraseBlock(hnor, hnor->pEAddress); + } else { + HAL_SFCNOR_EraseFinishCallback(hnor); + + /* Check the NOR memory status and update the controller state */ + hnor->State = HAL_SFCNOR_STATE_READY; + return; + } + } + } + + if (err_flag) { + SFCNOR_DumpInfo(hnor->Instance); + + __HAL_SFCNOR_CLEAR_ALL_INTC(hnor); + __HAL_SFCNOR_MASK_ALL_INTC(hnor); + + HAL_SFCNOR_ErrorCallback(hnor); + /* Check the NOR controller state */ + hnor->State = HAL_SFCNOR_STATE_READY; + } +} + +/** + * @brief Perform the NOR memory Initialization sequence in polling mode + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SFCNOR_Init(SFCNOR_HandleTypeDef *hnor) +{ + hnor->in_mode = POLL_MODE; + return SFCNOR_Init(hnor); +} + +/** + * @brief Perform the NOR memory Initialization sequence in interrupt mode + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SFCNOR_Init_IT(SFCNOR_HandleTypeDef *hnor) +{ + hnor->in_mode = IT_MODE; + return SFCNOR_Init(hnor); +} + +/** + * @brief Perform the NOR memory Initialization sequence in polling and dma mode + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SFCNOR_Init_PIO_DMA(SFCNOR_HandleTypeDef *hnor) +{ + hnor->in_mode = DMA_POLL_MODE; + return SFCNOR_Init(hnor); +} + +/** + * @brief Perform the NOR memory Initialization sequence in interrupt and dma mode + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SFCNOR_Init_IT_DMA(SFCNOR_HandleTypeDef *hnor) +{ + hnor->in_mode = DMA_IT_MODE; + return SFCNOR_Init(hnor); +} + +/** + * @brief Perform NOR memory De-Initialization sequence + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SFCNOR_DeInit(SFCNOR_HandleTypeDef *hnor) +{ +#if (USE_HAL_SFCNOR_REGISTER_CALLBACKS == 1) + if (hnor->MspDeInitCallback == NULL) { + hnor->MspDeInitCallback = HAL_SFCNOR_MspDeInit; + } + + /* DeInit the low level hardware */ + hnor->MspDeInitCallback(hnor); +#else + /* De-Initialize the low level hardware (MSP) */ + HAL_SFCNOR_MspDeInit(hnor); +#endif /* (USE_HAL_SFCNOR_REGISTER_CALLBACKS) */ + + /* Update the NOR controller state */ + hnor->State = HAL_SFCNOR_STATE_RESET; + + return HAL_OK; +} + +/** + * @brief NOR MSP Init + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval None + */ +__weak void HAL_SFCNOR_MspInit(SFCNOR_HandleTypeDef *hnor) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hnor); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_SFCNOR_MspInit could be implemented in the user file + */ +} + +/** + * @brief NOR MSP DeInit + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval None + */ +__weak void HAL_SFCNOR_MspDeInit(SFCNOR_HandleTypeDef *hnor) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hnor); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_SFCNOR_MspDeInit could be implemented in the user file + */ +} + +/** + * @brief NOR MSP Wait for Ready/Busy signal + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param Timeout Maximum timeout value + * @retval None + */ +__weak void HAL_SFCNOR_MspWait(SFCNOR_HandleTypeDef *hnor, uint32_t Timeout) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hnor); + UNUSED(Timeout); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_SFCNOR_MspWait could be implemented in the user file + */ +} + +/** + * @brief SFCNOR Erase completed callbacks + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval None + */ +__weak void HAL_SFCNOR_EraseFinishCallback(SFCNOR_HandleTypeDef *hnor) +{ + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SFCNOR_EraseFinishCallback can be implemented in the user file + */ +#if defined (USE_HAL_SFCNOR_REGISTER_CALLBACKS) && (USE_HAL_SFCNOR_REGISTER_CALLBACKS == 1U) + hnor->EraseFinishCallback(hnor); +#else + UNUSED(hnor); +#endif +} + +/** + * @brief Write completed callbacks + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval None + */ +__weak void HAL_SFCNOR_WriteFinishCallback(SFCNOR_HandleTypeDef *hnor) +{ + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SFCNOR_WriteFinishCallback can be implemented in the user file + */ +#if defined (USE_HAL_SFCNOR_REGISTER_CALLBACKS) && (USE_HAL_SFCNOR_REGISTER_CALLBACKS == 1U) + hnor->WriteFinishCallback(hnor); +#else + UNUSED(hnor); +#endif +} + +/** + * @brief Read completed callbacks + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval None + */ +__weak void HAL_SFCNOR_ReadFinishCallback(SFCNOR_HandleTypeDef *hnor) +{ + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SFCNOR_ReadFinishCallback can be implemented in the user file + */ +#if defined (USE_HAL_SFCNOR_REGISTER_CALLBACKS) && (USE_HAL_SFCNOR_REGISTER_CALLBACKS == 1U) + hnor->ReadFinishCallback(hnor); +#else + UNUSED(hnor); +#endif +} + +/** + * @brief SFCNOR error callbacks + * @param hnor: pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval None + */ +__weak void HAL_SFCNOR_ErrorCallback(SFCNOR_HandleTypeDef *hnor) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hnor); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SFCNOR_ErrorCallback can be implemented in the user file + */ +#if defined (USE_HAL_SFCNOR_REGISTER_CALLBACKS) && (USE_HAL_SFCNOR_REGISTER_CALLBACKS == 1U) + hnor->ErrorCallback(hnor); +#else + UNUSED(hnor); +#endif +} + +/** + * @brief Read NOR flash IDs + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param pNOR_ID pointer to flash IDs + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SFCNOR_Read_ID(SFCNOR_HandleTypeDef *hnor, unsigned int *pNOR_ID) +{ + struct sfc_cdt_xfer *xfer = &hnor->xfer; + unsigned char buf[3]; + + /* Check the NOR controller state */ + if (hnor->State == HAL_SFCNOR_STATE_BUSY) { + return HAL_BUSY; + } + /* Update the NOR controller state */ + hnor->State = HAL_SFCNOR_STATE_BUSY; + + SFCNOR_CdtXferInitParams(xfer); + + /* set Index */ + xfer->cmd_index = NOR_READ_ID; + + /* set addr */ + xfer->rowaddr = 0; + xfer->columnaddr = 0; + + /* set transfer config */ + xfer->dataen = ENABLE; + xfer->config.datalen = 3; + xfer->config.data_dir = GLB_TRAN_DIR_READ; + xfer->config.ops_mode = CPU_OPS; + xfer->config.buf = buf; + + /* use polling mode */ + SFCNOR_SyncCdt(hnor->Instance, xfer, 0); + SFCNOR_SrHandle(hnor, xfer); + + *pNOR_ID = ((buf[0] & 0xff) << 16) | ((buf[1] & 0xff) << 8) | (buf[2] & 0xff); + + /* Check the NOR controller state */ + hnor->State = HAL_SFCNOR_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Read data from NOR memory + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param pAddress pointer to Device address + * @param len read data len + * @param pData pointer to read data + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SFCNOR_Read(SFCNOR_HandleTypeDef *hnor, uint32_t pAddress, uint32_t len, unsigned char *pData) +{ + int tmp_len = 0, current_len = 0; + /* Check the NOR controller state */ + if (hnor->State == HAL_SFCNOR_STATE_BUSY) { + return HAL_BUSY; + } + + /* Update the NOR controller state */ + hnor->State = HAL_SFCNOR_STATE_BUSY; + + while ((int)len > 0) { + tmp_len = SFCNOR_Read(hnor, (unsigned int)pAddress + current_len, &pData[current_len], len); + current_len += tmp_len; + len -= tmp_len; + } + + /* Check the NOR controller state */ + hnor->State = HAL_SFCNOR_STATE_READY; + + if (len == 0) { + return HAL_OK; + } else { + return HAL_ERROR; + } +} + +/** + * @brief Program data to SFCNOR memory + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param pAddress Device address + * @param len Program len + * @param pData pointer to the data to write + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SFCNOR_Program(SFCNOR_HandleTypeDef *hnor, uint32_t pAddress, uint32_t len, unsigned char *pData) +{ + unsigned int page_offset, actual_len; + struct spi_nor_info *spi_nor_info = &hnor->spi_nor_info; + int writesize = spi_nor_info->page_size; + + /* Check the NOR controller state */ + if (hnor->State == HAL_SFCNOR_STATE_BUSY) { + return HAL_BUSY; + } + + /* Update the NOR controller state */ + hnor->State = HAL_SFCNOR_STATE_BUSY; + + page_offset = pAddress & (spi_nor_info->page_size - 1); + /* do all the bytes fit onto one page? */ + if (page_offset + len <= spi_nor_info->page_size) { + SFCNOR_Write(hnor, pAddress, len, pData); + } else { + int i; + + /* the size of data remaining on the first page */ + actual_len = spi_nor_info->page_size - page_offset; + SFCNOR_Write(hnor, pAddress, actual_len, pData); + + /* write everything in flash->page_size chunks */ + for (i = actual_len; i < len; i += writesize) { + actual_len = len - i; + if (actual_len >= writesize) { + actual_len = writesize; + } + SFCNOR_Write(hnor, pAddress + i, actual_len, pData + i); + } + } + + /* Check the NOR controller state */ + hnor->State = HAL_SFCNOR_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Erase the specified block of the SFCNOR memory + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param pAddress Block to erase address + * @param len Erase len + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SFCNOR_Erase_Block(SFCNOR_HandleTypeDef *hnor, uint32_t pAddress, uint32_t len) +{ + int ret; + uint32_t end; + struct spi_nor_info *spi_nor_info = &hnor->spi_nor_info; + int erasesize = spi_nor_info->erase_size; + + /* Check the NOR controller state */ + if (hnor->State == HAL_SFCNOR_STATE_BUSY) { + return HAL_BUSY; + } + + /* Update the NOR controller state */ + hnor->State = HAL_SFCNOR_STATE_BUSY; + + if (len % erasesize != 0) { + len = len - (len % erasesize) + erasesize; + } + + end = pAddress + len; + while (pAddress < end) { + ret = SFCNOR_EraseBlock(hnor, pAddress); + if (ret) { + prom_printk("erase error !\n"); + return ret; + } + pAddress += erasesize; + } + + /* Check the NOR memory status and update the controller state */ + hnor->State = HAL_SFCNOR_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Read data from SFCNOR memory in interrupt mode + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param pAddress pointer to Device address + * @param len read data len + * @param pData pointer to read data + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SFCNOR_Read_IT(SFCNOR_HandleTypeDef *hnor, uint32_t pAddress, uint32_t len, unsigned char *pData) +{ + /* Check the NOR controller state */ + if (hnor->State == HAL_SFCNOR_STATE_BUSY) { + return HAL_BUSY; + } + + /* Update the NOR controller state */ + hnor->State = HAL_SFCNOR_STATE_BUSY; + + SFCNOR_Read(hnor, (unsigned int)pAddress, pData, len); + + return HAL_OK; +} + +/** + * @brief Program data to SFCNOR memory in interrupt mode + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param pAddress Device address + * @param len Program len + * @param pData pointer to the data to write + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SFCNOR_Program_IT(SFCNOR_HandleTypeDef *hnor, uint32_t pAddress, uint32_t len, unsigned char *pData) +{ + unsigned int page_offset, actual_len; + struct spi_nor_info *spi_nor_info = &hnor->spi_nor_info; + + /* Check the NOR controller state */ + if (hnor->State == HAL_SFCNOR_STATE_BUSY) { + return HAL_BUSY; + } + + /* Update the NOR controller state */ + hnor->State = HAL_SFCNOR_STATE_BUSY; + + /* Initialize data control register */ + hnor->pTxAddress = pAddress; + hnor->pTxBuffPtr = (uint8_t *)pData; + hnor->TxXferSize = len; + + page_offset = pAddress & (spi_nor_info->page_size - 1); + /* do all the bytes fit onto one page? */ + if (page_offset + len <= spi_nor_info->page_size) { + SFCNOR_Write(hnor, pAddress, len, pData); + } else { + /* the size of data remaining on the first page */ + actual_len = spi_nor_info->page_size - page_offset; + SFCNOR_Write(hnor, pAddress, actual_len, pData); + } + + return HAL_OK; +} + +/** + * @brief Erase the specified block of the SFCNOR memory in interrupt mode + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param pAddress Block to erase address + * @param len Erase len + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SFCNOR_Erase_Block_IT(SFCNOR_HandleTypeDef *hnor, uint32_t pAddress, uint32_t len) +{ + struct spi_nor_info *spi_nor_info = &hnor->spi_nor_info; + int erasesize = spi_nor_info->erase_size; + + /* Check the NOR controller state */ + if (hnor->State == HAL_SFCNOR_STATE_BUSY) { + return HAL_BUSY; + } + + /* Update the NOR controller state */ + hnor->State = HAL_SFCNOR_STATE_BUSY; + + if (len % erasesize != 0) { + len = len - (len % erasesize) + erasesize; + } + + hnor->pEAddress = pAddress; + hnor->Elen = len; + SFCNOR_EraseBlock(hnor, pAddress); + + return HAL_OK; +} + +/** + * @brief Erase the entire SFCNOR chip. + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SFCNOR_Erase_Chip(SFCNOR_HandleTypeDef *hnor) +{ + /* Check the NOR controller state */ + if (hnor->State == HAL_SFCNOR_STATE_BUSY) { + return HAL_BUSY; + } + + return HAL_OK; +} + +#if (USE_HAL_SFCNOR_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User NOR Callback + * To be used instead of the weak (surcharged) predefined callback + * @param hnor : NOR handle + * @param CallbackId : ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_SFCNOR_ERASE_FINISH_CB_ID NOR Erase Finish callback ID + * @arg @ref HAL_SFCNOR_WRITE_FINISH_CB_ID NOR Write Finish callback ID + * @arg @ref HAL_SFCNOR_READ_FINISH_CB_ID NOR Read Finish callback ID + * @arg @ref HAL_SFCNOR_ERROR_CB_ID NOR Error callback ID + * @arg @ref HAL_SFCNOR_MSP_INIT_CB_ID NOR MspInit callback ID + * @arg @ref HAL_SFCNOR_MSP_DEINIT_CB_ID NOR MspDeInit callback ID + * @param pCallback : pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_SFCNOR_RegisterCallback(SFCNOR_HandleTypeDef *hnor, HAL_SFCNOR_CallbackIDTypeDef CallbackId, pSFCNOR_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + HAL_SFCNOR_StateTypeDef state; + + if (pCallback == NULL) { + return HAL_ERROR; + } + + state = hnor->State; + if ((state == HAL_SFCNOR_STATE_READY) || (state == HAL_SFCNOR_STATE_RESET) || (state == HAL_SFCNOR_STATE_PROTECTED)) { + switch (CallbackId) { + case HAL_SFCNOR_ERASE_FINISH_CB_ID : + hnor->EraseFinishCallback = pCallback; + break; + case HAL_SFCNOR_WRITE_FINISH_CB_ID : + hnor->WriteFinishCallback = pCallback; + break; + case HAL_SFCNOR_READ_FINISH_CB_ID : + hnor->ReadFinishCallback = pCallback; + break; + case HAL_SFCNOR_ERROR_CB_ID : + hnor->ErrorCallback = pCallback; + break; + case HAL_SFCNOR_MSP_INIT_CB_ID : + hnor->MspInitCallback = pCallback; + break; + case HAL_SFCNOR_MSP_DEINIT_CB_ID : + hnor->MspDeInitCallback = pCallback; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } else { + /* update return status */ + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Unregister a User SFCNOR Callback + * SFCNOR Callback is redirected to the weak (surcharged) predefined callback + * @param hnor : SFCNOR handle + * @param CallbackId : ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_SFCNOR_ERASE_FINISH_CB_ID NOR Erase Finish callback ID + * @arg @ref HAL_SFCNOR_WRITE_FINISH_CB_ID NOR Write Finish callback ID + * @arg @ref HAL_SFCNOR_READ_FINISH_CB_ID NOR Read Finish callback ID + * @arg @ref HAL_SFCNOR_ERROR_CB_ID NOR Error callback ID + * @arg @ref HAL_SFCNOR_MSP_INIT_CB_ID NOR MspInit callback ID + * @arg @ref HAL_SFCNOR_MSP_DEINIT_CB_ID NOR MspDeInit callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_SFCNOR_UnRegisterCallback(SFCNOR_HandleTypeDef *hnor, HAL_SFCNOR_CallbackIDTypeDef CallbackId) +{ + HAL_StatusTypeDef status = HAL_OK; + HAL_SFCNOR_StateTypeDef state; + + state = hnor->State; + if ((state == HAL_SFCNOR_STATE_READY) || (state == HAL_SFCNOR_STATE_RESET) || (state == HAL_SFCNOR_STATE_PROTECTED)) { + switch (CallbackId) { + case HAL_SFCNOR_ERASE_FINISH_CB_ID : + hnor->EraseFinishCallback = HAL_SFCNOR_EraseFinishCallback; + break; + case HAL_SFCNOR_WRITE_FINISH_CB_ID : + hnor->WriteFinishCallback = HAL_SFCNOR_WriteFinishCallback; + break; + case HAL_SFCNOR_READ_FINISH_CB_ID : + hnor->ReadFinishCallback = HAL_SFCNOR_ReadFinishCallback; + break; + case HAL_SFCNOR_ERROR_CB_ID : + hnor->ErrorCallback = HAL_SFCNOR_ErrorCallback; + break; + case HAL_SFCNOR_MSP_INIT_CB_ID : + hnor->MspInitCallback = HAL_SFCNOR_MspInit; + break; + case HAL_SFCNOR_MSP_DEINIT_CB_ID : + hnor->MspDeInitCallback = HAL_SFCNOR_MspDeInit; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } else { + /* update return status */ + status = HAL_ERROR; + } + + return status; +} +#endif /* (USE_HAL_SFCNOR_REGISTER_CALLBACKS) */ + +/** + * @brief return the NOR controller state + * @param hnor pointer to a SFCNOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval NOR controller state + */ +HAL_SFCNOR_StateTypeDef HAL_SFCNOR_GetState(SFCNOR_HandleTypeDef *hnor) +{ + return hnor->State; +} /** * @} - */ + */ /** * @} - */ + */ diff --git a/drivers/drivers-x2600/src/x2600_ll_sfc.c b/drivers/drivers-x2600/src/x2600_ll_sfc.c index b4d5c547..934d9898 100755 --- a/drivers/drivers-x2600/src/x2600_ll_sfc.c +++ b/drivers/drivers-x2600/src/x2600_ll_sfc.c @@ -17,98 +17,587 @@ [!!!!删除此内容,添加针对模块的使用方法说明,例如: 配置,启动/停止,状态,重点提醒等等.!!!!] @endverbatim */ - + /* 1.头文件 (Includes)------------------------------------------------ */ +#include "x2600_ll_sfc.h" /** @addtogroup g_X2600_SFC_LL_Driver * @{ */ - + /* 2.私有常量定义Private Constants -------------------------------------- */ /** - * @addtogroup SFC_private_constants + * @addtogroup SFC_private_constants * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 3. 私有类型定义 (Private Types) -------------------------------------- */ /** - * @addtogroup SFC_private_types + * @addtogroup SFC_private_types * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 4. 私有宏定义 (Private Macros) -------------------------------------- */ /** - * @addtogroup SFC_private_macros + * @addtogroup SFC_private_macros * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 5. 私有变量申明 Private Variables ------------------------------------ */ /** - * @addtogroup SFC_private_var + * @addtogroup SFC_private_var * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 6. 私有函数申明 (Private Funcs) -------------------------------------- */ /** - * @addtogroup SFC_private_funcs + * @addtogroup SFC_private_funcs * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 7. 私有函数实现 (Private Funcs) -------------------------------------- */ /** * @defgroup SFC_private_funcs_impl SFC 私有函数实现 * @{ */ - + // 删除此行, 添加内容 // 删除此行, 添加内容 /** * @} - */ + */ /* 8. 导出函数实现------------------------------------------------------- */ /** * @defgroup SFC_exported_funcs_impl SFC 导出函数实现 * @{ */ - -// 删除此行, 添加内容 -// 删除此行, 添加内容 + +/** + * @brief dump sfc registers value + * @param SFCNORx pointer to a SFC_TypeDef structure that contains + * the sfc registers information. + * @retval None + */ +void SFCNOR_DumpReg(SFC_TypeDef *SFCNORx) +{ + int i = 0; + + prom_printk("\nSFC_GLB0 = %08x\n", SFCNORx->GLB0); + prom_printk("SFC_DEV_CONF = %08x\n", SFCNORx->DEV_CONF); + prom_printk("SFC_DEV_STA_EXP = %08x\n", SFCNORx->DEV_STA_EXP); + prom_printk("SFC_DEV0_STA_RT = %08x\n", SFCNORx->DEV0_STA_RT); + prom_printk("SFC_DEV_STA_MASK = %08x\n", SFCNORx->DEV_STA_MSK); + for (i = 0; i < 6; i++) { + prom_printk("SFC_TRAN_CONF0(%d) = %08x\n", i, SFCNORx->TRAN_CFG0n[i]); + } + prom_printk("SFC_TRAN_LEN = %08x\n", SFCNORx->TRAN_LEN); + for (i = 0; i < 6; i++) { + prom_printk("SFC_DEV_ADDR%d = %08x\n", i, SFCNORx->DEV_ADRn[i]); + prom_printk("SFC_DEV_ADDR_PLUS%d = %08x\n", i, SFCNORx->DEV_PLUSn[i]); + } + + prom_printk("SFC_MEM_ADDR = %08x\n", SFCNORx->MEM_ADDR); + prom_printk("SFC_TRIG = %08x\n", SFCNORx->TRIG); + prom_printk("SFC_SR = %08x\n", SFCNORx->SR); + prom_printk("SFC_SCR = %08x\n", SFCNORx->SCR); + prom_printk("SFC_INTC = %08x\n", SFCNORx->INTC); + prom_printk("SFC_FSM = %08x\n", SFCNORx->FSM); + prom_printk("SFC_CGE = %08x\n", SFCNORx->CGE); + prom_printk("SFC_CMD_IDX = %08x\n", SFCNORx->CMD_IDX); + prom_printk("SFC_COL_ADDR = %08x\n", SFCNORx->COL_ADDR); + prom_printk("SFC_ROW_ADDR = %08x\n", SFCNORx->ROW_ADDR); + prom_printk("SFC_STA_ADDR0 = %08x\n", SFCNORx->STA_ADDR0); + prom_printk("SFC_STA_ADDR1 = %08x\n", SFCNORx->STA_ADDR1); + prom_printk("SFC_DES_ADDR = %08x\n", SFCNORx->DES_ADDR); + prom_printk("SFC_GLB1 = %08x\n", SFCNORx->GLB1); + prom_printk("SFC_DEV1_STA_RT = %08x\n", SFCNORx->DEV1_STA_RT); + for (i = 0; i < 6; i++) { + prom_printk("SFC_TRAN_CONF1(%d) = %08x\n", i, SFCNORx->TRAN_CFG1n[i]); + } +} + +/** + * @brief dump cdt info + * @param SFCNORx pointer to a SFC_TypeDef structure that contains + * the sfc registers information. + * @retval None + */ +void SFCNOR_DumpCdt(SFC_TypeDef *SFCNORx) +{ + struct sfc_cdt *cdt; + int i; + + cdt = (struct sfc_cdt *)SFCNORx->CDTn; + for (i = 0; i < 32; i++) { + prom_printk("\nnum------->%d\n", i); + prom_printk("link:%02x, ENDIAN:%02x, WORD_UINT:%02x, TRAN_MODE:%02x, ADDR_KIND:%02x\n", + (cdt[i].link >> 31) & 0x1, (cdt[i].link >> 18) & 0x1, + (cdt[i].link >> 16) & 0x3, (cdt[i].link >> 4) & 0xf, + (cdt[i].link >> 0) & 0x3 + ); + prom_printk("CLK_MODE:%02x, ADDR_WIDTH:%02x, POLL_EN:%02x, CMD_EN:%02x,PHASE_FORMAT:%02x, DMY_BITS:%02x, DATA_EN:%02x, TRAN_CMD:%04x\n", + (cdt[i].xfer >> 29) & 0x7, (cdt[i].xfer >> 26) & 0x7, + (cdt[i].xfer >> 25) & 0x1, (cdt[i].xfer >> 24) & 0x1, + (cdt[i].xfer >> 23) & 0x1, (cdt[i].xfer >> 17) & 0x3f, + (cdt[i].xfer >> 16) & 0x1, (cdt[i].xfer >> 0) & 0xffff + ); + prom_printk("DEV_STA_EXP:%08x\n", cdt[i].staExp); + prom_printk("DEV_STA_MSK:%08x\n", cdt[i].staMsk); + } +} + +/** + * @brief dump sfc registers value and cdt information + * @param SFCNORx pointer to a SFC_TypeDef structure that contains + * the sfc registers information. + * @retval None + */ +void SFCNOR_DumpInfo(SFC_TypeDef *SFCNORx) +{ + prom_printk("\n######################### sfc dump ###########################\n"); + prom_printk("\nsfc reg: \n"); + SFCNOR_DumpReg(SFCNORx); + prom_printk("\nsfc CDT table: \n"); + SFCNOR_DumpCdt(SFCNORx); + prom_printk("\n######################### sfc dump end ###########################\n"); +} + +/** + * @brief dump cloner parameters + * @param spi_nor_info pointer to a spi_nor_info structure that contains + * the nor flash information. + * @retval None + */ +void SFCNOR_DumpClonerParams(struct spi_nor_info *spi_nor_info) +{ + prom_printk("name=%s\n", spi_nor_info->name); + prom_printk("id=0x%x\n", spi_nor_info->id); + + prom_printk("read_standard->cmd=0x%x\n", spi_nor_info->read_standard.cmd); + prom_printk("read_standard->dummy=0x%x\n", spi_nor_info->read_standard.dummy_byte); + prom_printk("read_standard->addr_nbyte=0x%x\n", spi_nor_info->read_standard.addr_nbyte); + prom_printk("read_standard->transfer_mode=0x%x\n", spi_nor_info->read_standard.transfer_mode); + + prom_printk("read_quad->cmd=0x%x\n", spi_nor_info->read_quad.cmd); + prom_printk("read_quad->dummy=0x%x\n", spi_nor_info->read_quad.dummy_byte); + prom_printk("read_quad->addr_nbyte=0x%x\n", spi_nor_info->read_quad.addr_nbyte); + prom_printk("read_quad->transfer_mode=0x%x\n", spi_nor_info->read_quad.transfer_mode); + + prom_printk("write_standard->cmd=0x%x\n", spi_nor_info->write_standard.cmd); + prom_printk("write_standard->dummy=0x%x\n", spi_nor_info->write_standard.dummy_byte); + prom_printk("write_standard->addr_nbyte=0x%x\n", spi_nor_info->write_standard.addr_nbyte); + prom_printk("write_standard->transfer_mode=0x%x\n", spi_nor_info->write_standard.transfer_mode); + + prom_printk("write_quad->cmd=0x%x\n", spi_nor_info->write_quad.cmd); + prom_printk("write_quad->dummy=0x%x\n", spi_nor_info->write_quad.dummy_byte); + prom_printk("write_quad->addr_nbyte=0x%x\n", spi_nor_info->write_quad.addr_nbyte); + prom_printk("write_quad->transfer_mode=0x%x\n", spi_nor_info->write_quad.transfer_mode); + + prom_printk("sector_erase->cmd=0x%x\n", spi_nor_info->sector_erase.cmd); + prom_printk("sector_erase->dummy=0x%x\n", spi_nor_info->sector_erase.dummy_byte); + prom_printk("sector_erase->addr_nbyte=0x%x\n", spi_nor_info->sector_erase.addr_nbyte); + prom_printk("sector_erase->transfer_mode=0x%x\n", spi_nor_info->sector_erase.transfer_mode); + + prom_printk("wr_en->cmd=0x%x\n", spi_nor_info->wr_en.cmd); + prom_printk("wr_en->dummy=0x%x\n", spi_nor_info->wr_en.dummy_byte); + prom_printk("wr_en->addr_nbyte=0x%x\n", spi_nor_info->wr_en.addr_nbyte); + prom_printk("wr_en->transfer_mode=0x%x\n", spi_nor_info->wr_en.transfer_mode); + + prom_printk("en4byte->cmd=0x%x\n", spi_nor_info->en4byte.cmd); + prom_printk("en4byte->dummy=0x%x\n", spi_nor_info->en4byte.dummy_byte); + prom_printk("en4byte->addr_nbyte=0x%x\n", spi_nor_info->en4byte.addr_nbyte); + prom_printk("en4byte->transfer_mode=0x%x\n", spi_nor_info->en4byte.transfer_mode); + + prom_printk("quad_set->cmd=0x%x\n", spi_nor_info->quad_set.cmd); + prom_printk("quad_set->bit_shift=0x%x\n", spi_nor_info->quad_set.bit_shift); + prom_printk("quad_set->mask=0x%x\n", spi_nor_info->quad_set.mask); + prom_printk("quad_set->val=0x%x\n", spi_nor_info->quad_set.val); + prom_printk("quad_set->len=0x%x\n", spi_nor_info->quad_set.len); + prom_printk("quad_set->dummy=0x%x\n", spi_nor_info->quad_set.dummy); + + prom_printk("quad_get->cmd=0x%x\n", spi_nor_info->quad_get.cmd); + prom_printk("quad_get->bit_shift=0x%x\n", spi_nor_info->quad_get.bit_shift); + prom_printk("quad_get->mask=0x%x\n", spi_nor_info->quad_get.mask); + prom_printk("quad_get->val=0x%x\n", spi_nor_info->quad_get.val); + prom_printk("quad_get->len=0x%x\n", spi_nor_info->quad_get.len); + prom_printk("quad_get->dummy=0x%x\n", spi_nor_info->quad_get.dummy); + + prom_printk("busy->cmd=0x%x\n", spi_nor_info->busy.cmd); + prom_printk("busy->bit_shift=0x%x\n", spi_nor_info->busy.bit_shift); + prom_printk("busy->mask=0x%x\n", spi_nor_info->busy.mask); + prom_printk("busy->val=0x%x\n", spi_nor_info->busy.val); + prom_printk("busy->len=0x%x\n", spi_nor_info->busy.len); + prom_printk("busy->dummy=0x%x\n", spi_nor_info->busy.dummy); + + prom_printk("quad_ops_mode=%d\n", spi_nor_info->quad_ops_mode); + prom_printk("addr_ops_mode=%d\n", spi_nor_info->addr_ops_mode); + + prom_printk("tCHSH=%d\n", spi_nor_info->tCHSH); + prom_printk("tSLCH=%d\n", spi_nor_info->tSLCH); + prom_printk("tSHSL_RD=%d\n", spi_nor_info->tSHSL_RD); + prom_printk("tSHSL_WR=%d\n", spi_nor_info->tSHSL_WR); + + prom_printk("chip_size=%d\n", spi_nor_info->chip_size); + prom_printk("page_size=%d\n", spi_nor_info->page_size); + prom_printk("erase_size=%d\n", spi_nor_info->erase_size); + + prom_printk("chip_erase_cmd=0x%x\n", spi_nor_info->chip_erase_cmd); +} + +/** + * @brief memcpy function + * @param dst pointer to copy dest address. + * @param src pointer to copy source address. + * @param count copy data size. + * @retval None + */ +void SFCNOR_memcpy(void *dst, void *src, unsigned int count) +{ + if ((dst == NULL) || (src == NULL)) { + return; + } + char *pdst = (char *)dst; + char *psrc = (char *)src; + while (count--) { + *pdst++ = *psrc++; + } +} + +/** + * @brief create base command to cdt table + * @param SFCNORx pointer to a SFC_TypeDef structure that contains + * the sfc registers information. + * @retval None + */ +void SFCNOR_CreateCdtTable_First(SFC_TypeDef *SFCNORx) +{ + struct sfc_cdt *cdt = (struct sfc_cdt *)&SFCNORx->CDTn; + /* 1.nor reset */ + cdt[NOR_RESET_ENABLE].link = __HAL_SFCNOR_CMD_LINK(1, DEFAULT_ADDRMODE, TM_STD_SPI); + cdt[NOR_RESET_ENABLE].xfer = __HAL_SFCNOR_CMD_XFER(0, DISABLE, 0, DISABLE, SPINOR_OP_RSTEN); + cdt[NOR_RESET_ENABLE].staExp = 0; + cdt[NOR_RESET_ENABLE].staMsk = 0; + + cdt[NOR_RESET].link = __HAL_SFCNOR_CMD_LINK(0, DEFAULT_ADDRMODE, TM_STD_SPI); + cdt[NOR_RESET].xfer = __HAL_SFCNOR_CMD_XFER(0, DISABLE, 0, DISABLE, SPINOR_OP_RST); + cdt[NOR_RESET].staExp = 0; + cdt[NOR_RESET].staMsk = 0; + + /* 2.nor read id */ + cdt[NOR_READ_ID].link = __HAL_SFCNOR_CMD_LINK(0, DEFAULT_ADDRMODE, TM_STD_SPI); + cdt[NOR_READ_ID].xfer = __HAL_SFCNOR_CMD_XFER(0, DISABLE, 0, ENABLE, SPINOR_OP_RDID); + cdt[NOR_READ_ID].staExp = 0; + cdt[NOR_READ_ID].staMsk = 0; + + /* 3. nor get status */ + cdt[NOR_GET_STATUS].link = __HAL_SFCNOR_CMD_LINK(0, DEFAULT_ADDRMODE, TM_STD_SPI); + cdt[NOR_GET_STATUS].xfer = __HAL_SFCNOR_CMD_XFER(0, DISABLE, 0, ENABLE, SPINOR_OP_RDSR); + cdt[NOR_GET_STATUS].staExp = 0; + cdt[NOR_GET_STATUS].staMsk = 0; + + cdt[NOR_GET_STATUS_1].link = __HAL_SFCNOR_CMD_LINK(0, DEFAULT_ADDRMODE, TM_STD_SPI); + cdt[NOR_GET_STATUS_1].xfer = __HAL_SFCNOR_CMD_XFER(0, DISABLE, 0, ENABLE, SPINOR_OP_RDSR_1); + cdt[NOR_GET_STATUS_1].staExp = 0; + cdt[NOR_GET_STATUS_1].staMsk = 0; + + cdt[NOR_GET_STATUS_2].link = __HAL_SFCNOR_CMD_LINK(0, DEFAULT_ADDRMODE, TM_STD_SPI); + cdt[NOR_GET_STATUS_2].xfer = __HAL_SFCNOR_CMD_XFER(0, DISABLE, 0, ENABLE, SPINOR_OP_RDSR_2); + cdt[NOR_GET_STATUS_2].staExp = 0; + cdt[NOR_GET_STATUS_2].staMsk = 0; + + /* 4.nor singleRead */ + cdt[NOR_READ_STANDARD].link = __HAL_SFCNOR_CMD_LINK(0, ROW_ADDR, TM_STD_SPI); + cdt[NOR_READ_STANDARD].xfer = __HAL_SFCNOR_CMD_XFER(DEFAULT_ADDRSIZE, DISABLE, 0, ENABLE, SPINOR_OP_READ); + cdt[NOR_READ_STANDARD].staExp = 0; + cdt[NOR_READ_STANDARD].staMsk = 0; + prom_printk("create CDT index: %d ~ %d, index number:%d.\n", NOR_RESET_ENABLE, NOR_READ_STANDARD, (NOR_READ_STANDARD - NOR_RESET_ENABLE)); +} + +/** + * @brief create specifc flash command to cdt table + * @param SFCNORx pointer to a SFC_TypeDef structure that contains + * the sfc registers information. + * @param spi_nor_info pointer to a spi_nor_info structure that contains + * the nor flash information. + * @retval None + */ +void SFCNOR_CreateCdtTable_Second(SFC_TypeDef *SFCNORx, struct spi_nor_info *params) +{ + struct sfc_cdt *cdt = (struct sfc_cdt *)&SFCNORx->CDTn; + /* 4.nor singleRead */ + cdt[NOR_READ_STANDARD].link = __HAL_SFCNOR_CMD_LINK(0, ROW_ADDR, params->read_standard.transfer_mode); + cdt[NOR_READ_STANDARD].xfer = __HAL_SFCNOR_CMD_XFER(params->read_standard.addr_nbyte, DISABLE, params->read_standard.dummy_byte, ENABLE, params->read_standard.cmd); + cdt[NOR_READ_STANDARD].staExp = 0; + cdt[NOR_READ_STANDARD].staMsk = 0; + + /* 5.nor quadRead */ + cdt[NOR_READ_QUAD].link = __HAL_SFCNOR_CMD_LINK(0, ROW_ADDR, params->read_quad.transfer_mode); + cdt[NOR_READ_QUAD].xfer = __HAL_SFCNOR_CMD_XFER(params->read_quad.addr_nbyte, DISABLE, params->read_quad.dummy_byte, ENABLE, params->read_quad.cmd); + cdt[NOR_READ_QUAD].staExp = 0; + cdt[NOR_READ_QUAD].staMsk = 0; + + /* 6. nor writeStandard */ + cdt[NOR_WRITE_STANDARD_ENABLE].link = __HAL_SFCNOR_CMD_LINK(1, DEFAULT_ADDRMODE, params->wr_en.transfer_mode); + cdt[NOR_WRITE_STANDARD_ENABLE].xfer = __HAL_SFCNOR_CMD_XFER(params->wr_en.addr_nbyte, DISABLE, params->wr_en.dummy_byte, DISABLE, params->wr_en.cmd); + cdt[NOR_WRITE_STANDARD_ENABLE].staExp = 0; + cdt[NOR_WRITE_STANDARD_ENABLE].staMsk = 0; + cdt[NOR_WRITE_STANDARD].link = __HAL_SFCNOR_CMD_LINK(1, ROW_ADDR, params->write_standard.transfer_mode); + cdt[NOR_WRITE_STANDARD].xfer = __HAL_SFCNOR_CMD_XFER(params->write_standard.addr_nbyte, DISABLE, params->write_standard.dummy_byte, ENABLE, params->write_standard.cmd); + cdt[NOR_WRITE_STANDARD].staExp = 0; + cdt[NOR_WRITE_STANDARD].staMsk = 0; + cdt[NOR_WRITE_STANDARD_FINISH].link = __HAL_SFCNOR_CMD_LINK(0, DEFAULT_ADDRMODE, TM_STD_SPI); + cdt[NOR_WRITE_STANDARD_FINISH].xfer = __HAL_SFCNOR_CMD_XFER(0, ENABLE, params->busy.dummy, DISABLE, params->busy.cmd); + cdt[NOR_WRITE_STANDARD_FINISH].staExp = (params->busy.val << params->busy.bit_shift); + cdt[NOR_WRITE_STANDARD_FINISH].staMsk = (params->busy.mask << params->busy.bit_shift); + + /* 7. nor writeQuad */ + cdt[NOR_WRITE_QUAD_ENABLE].link = __HAL_SFCNOR_CMD_LINK(1, DEFAULT_ADDRMODE, params->wr_en.transfer_mode); + cdt[NOR_WRITE_QUAD_ENABLE].xfer = __HAL_SFCNOR_CMD_XFER(params->wr_en.addr_nbyte, DISABLE, params->wr_en.dummy_byte, DISABLE, params->wr_en.cmd); + cdt[NOR_WRITE_QUAD_ENABLE].staExp = 0; + cdt[NOR_WRITE_QUAD_ENABLE].staMsk = 0; + cdt[NOR_WRITE_QUAD].link = __HAL_SFCNOR_CMD_LINK(1, ROW_ADDR, params->write_quad.transfer_mode); + cdt[NOR_WRITE_QUAD].xfer = __HAL_SFCNOR_CMD_XFER(params->write_quad.addr_nbyte, DISABLE, params->write_quad.dummy_byte, ENABLE, params->write_quad.cmd); + cdt[NOR_WRITE_QUAD].staExp = 0; + cdt[NOR_WRITE_QUAD].staMsk = 0; + cdt[NOR_WRITE_QUAD_FINISH].link = __HAL_SFCNOR_CMD_LINK(0, DEFAULT_ADDRMODE, TM_STD_SPI); + cdt[NOR_WRITE_QUAD_FINISH].xfer = __HAL_SFCNOR_CMD_XFER(0, ENABLE, params->busy.dummy, DISABLE, params->busy.cmd); + cdt[NOR_WRITE_QUAD_FINISH].staExp = (params->busy.val << params->busy.bit_shift); + cdt[NOR_WRITE_QUAD_FINISH].staMsk = (params->busy.mask << params->busy.bit_shift); + + /* 8. nor erase */ + cdt[NOR_ERASE_WRITE_ENABLE].link = __HAL_SFCNOR_CMD_LINK(1, DEFAULT_ADDRMODE, params->wr_en.transfer_mode); + cdt[NOR_ERASE_WRITE_ENABLE].xfer = __HAL_SFCNOR_CMD_XFER(params->wr_en.addr_nbyte, DISABLE, params->wr_en.dummy_byte, DISABLE, params->wr_en.cmd); + cdt[NOR_ERASE_WRITE_ENABLE].staExp = 0; + cdt[NOR_ERASE_WRITE_ENABLE].staMsk = 0; + cdt[NOR_ERASE].link = __HAL_SFCNOR_CMD_LINK(1, ROW_ADDR, params->sector_erase.transfer_mode); + cdt[NOR_ERASE].xfer = __HAL_SFCNOR_CMD_XFER(params->sector_erase.addr_nbyte, DISABLE, params->sector_erase.dummy_byte, DISABLE, params->sector_erase.cmd); + cdt[NOR_ERASE].staExp = 0; + cdt[NOR_ERASE].staMsk = 0; + cdt[NOR_ERASE_FINISH].link = __HAL_SFCNOR_CMD_LINK(0, DEFAULT_ADDRMODE, TM_STD_SPI); + cdt[NOR_ERASE_FINISH].xfer = __HAL_SFCNOR_CMD_XFER(0, ENABLE, params->busy.dummy, DISABLE, params->busy.cmd); + cdt[NOR_ERASE_FINISH].staExp = (params->busy.val << params->busy.bit_shift); + cdt[NOR_ERASE_FINISH].staMsk = (params->busy.mask << params->busy.bit_shift); + + /* 9. quad mode */ + if (params->quad_ops_mode) { + cdt[NOR_QUAD_SET_ENABLE].link = __HAL_SFCNOR_CMD_LINK(1, DEFAULT_ADDRMODE, params->wr_en.transfer_mode); + cdt[NOR_QUAD_SET_ENABLE].xfer = __HAL_SFCNOR_CMD_XFER(params->wr_en.addr_nbyte, DISABLE, params->wr_en.dummy_byte, DISABLE, params->wr_en.cmd); + cdt[NOR_QUAD_SET_ENABLE].staExp = 0; + cdt[NOR_QUAD_SET_ENABLE].staMsk = 0; + cdt[NOR_QUAD_SET].link = __HAL_SFCNOR_CMD_LINK(1, DEFAULT_ADDRMODE, TM_STD_SPI); + cdt[NOR_QUAD_SET].xfer = __HAL_SFCNOR_CMD_XFER(0, DISABLE, params->quad_set.dummy, ENABLE, params->quad_set.cmd); + cdt[NOR_QUAD_SET].staExp = (params->quad_set.val << params->quad_set.bit_shift); + cdt[NOR_QUAD_SET].staMsk = (params->quad_set.mask << params->quad_set.bit_shift); + cdt[NOR_QUAD_FINISH].link = __HAL_SFCNOR_CMD_LINK(1, DEFAULT_ADDRMODE, TM_STD_SPI); + cdt[NOR_QUAD_FINISH].xfer = __HAL_SFCNOR_CMD_XFER(0, ENABLE, params->busy.dummy, DISABLE, params->busy.cmd); + cdt[NOR_QUAD_FINISH].staExp = (params->busy.val << params->busy.bit_shift); + cdt[NOR_QUAD_FINISH].staMsk = (params->busy.mask << params->busy.bit_shift); + cdt[NOR_QUAD_GET].link = __HAL_SFCNOR_CMD_LINK(0, DEFAULT_ADDRMODE, TM_STD_SPI); + cdt[NOR_QUAD_GET].xfer = __HAL_SFCNOR_CMD_XFER(0, ENABLE, params->quad_get.dummy, DISABLE, params->quad_get.cmd); + cdt[NOR_QUAD_GET].staExp = (params->quad_get.val << params->quad_get.bit_shift); + cdt[NOR_QUAD_GET].staMsk = (params->quad_get.mask << params->quad_get.bit_shift); + } + + /* 10. nor write ENABLE */ + cdt[NOR_WRITE_ENABLE].link = __HAL_SFCNOR_CMD_LINK(0, DEFAULT_ADDRMODE, params->wr_en.transfer_mode); + cdt[NOR_WRITE_ENABLE].xfer = __HAL_SFCNOR_CMD_XFER(params->wr_en.addr_nbyte, DISABLE, params->wr_en.dummy_byte, DISABLE, params->wr_en.cmd); + cdt[NOR_WRITE_ENABLE].staExp = 0; + cdt[NOR_WRITE_ENABLE].staMsk = 0; + + /* 11. entry 4byte mode */ + cdt[NOR_EN_4BYTE].link = __HAL_SFCNOR_CMD_LINK(0, DEFAULT_ADDRMODE, params->en4byte.transfer_mode); + cdt[NOR_EN_4BYTE].xfer = __HAL_SFCNOR_CMD_XFER(params->en4byte.addr_nbyte, DISABLE, params->en4byte.dummy_byte, DISABLE, params->en4byte.cmd); + cdt[NOR_EN_4BYTE].staExp = 0; + cdt[NOR_EN_4BYTE].staMsk = 0; + + prom_printk("create CDT index: %d ~ %d, index number:%d.\n", NOR_READ_STANDARD, NOR_EN_4BYTE, (NOR_EN_4BYTE - NOR_READ_STANDARD)); +} + +/** + * @brief initialize cdt xfer + * @param xfer sfc cdt configure value + * @retval None + */ +void SFCNOR_CdtXferInitParams(struct sfc_cdt_xfer *xfer) +{ + xfer->cmd_index = 0; + xfer->dataen = 0; + xfer->dmaDescAddr = 0; + xfer->config.datalen = 0; + xfer->config.cur_len = 0; + xfer->config.data_dir = 0; + xfer->config.ops_mode = 0; + xfer->config.buf = NULL; + xfer->columnaddr = 0; + xfer->rowaddr = 0; + xfer->staaddr0 = 0; + xfer->staaddr1 = 0; +} + +/** + * @brief initialize SFCNOR register + * @param SFCNORx pointer to a SFC_TypeDef structure that contains + * the sfc registers information. + * @retval None + */ +void SFCNOR_RegInit(SFC_TypeDef *SFCNORx) +{ + int n; + for (n = 0; n < 6; n++) { + CLEAR_REG(SFCNORx->TRAN_CFG0n[n]); + CLEAR_REG(SFCNORx->TRAN_CFG1n[n]); + CLEAR_REG(SFCNORx->DEV_ADRn[n]); + CLEAR_REG(SFCNORx->DEV_PLUSn[n]); + } + for (n = 0; n < 256; n++) { + CLEAR_REG(SFCNORx->CDTn[n]); + } + + CLEAR_REG(SFCNORx->DEV_CONF); + CLEAR_REG(SFCNORx->DEV_STA_EXP); + CLEAR_REG(SFCNORx->DEV_STA_MSK); + CLEAR_REG(SFCNORx->TRAN_LEN); + CLEAR_REG(SFCNORx->MEM_ADDR); + CLEAR_REG(SFCNORx->TRIG); + CLEAR_REG(SFCNORx->SCR); + CLEAR_REG(SFCNORx->INTC); + CLEAR_REG(SFCNORx->CGE); + CLEAR_REG(SFCNORx->DR); +} + +/** + * @brief set SFCNOR control register + * @param SFCNORx pointer to a SFC_TypeDef structure that contains + * the sfc registers information. + * @param in_mode data transfer mode + * @retval None + */ +void SFCNOR_CtlInit(SFC_TypeDef *SFCNORx, OperationMode in_mode) +{ + assert_param(IS_SFCNOR_INSTANCE(SFCNORx)); + assert_param(IS_SFCNOR_MODE(in_mode)); + + SFCNOR_RegInit(SFCNORx); + SFCNOR_TRIG_SET_STOP(SFCNORx); + SFCNOR_SET_HOLD(SFCNORx); + SFCNOR_SET_WP(SFCNORx); + if ((in_mode == DMA_IT_MODE) || (in_mode == DMA_POLL_MODE)) { + SFCNOR_SET_DES_EN(SFCNORx, 1); + } else { + SFCNOR_SET_DES_EN(SFCNORx, 0); + } + SFCNOR_CLEAR_ALL_INTC(SFCNORx); + SFCNOR_MASK_ALL_INTC(SFCNORx); + MODIFY_REG(SFCNORx->GLB0, SFC_GLB0_THRESHOLD_Msk, (THRESHOLD << SFC_GLB0_THRESHOLD_Pos)); + SFCNOR_SET_CLOCK_PHASE(SFCNORx, 0); + SFCNOR_SET_CLOCK_POLARITY(SFCNORx, 0); + SFCNOR_SET_CE(SFCNORx, 1); + /* use CDT mode */ + SFCNOR_SET_CDT_ENABLE(SFCNORx); + /* slave mode */ + SFCNOR_SET_TRANSFER_MODE(SFCNORx, 0); + /* config sfc */ + SFCNOR_SET_FLASH_TIMING(SFCNORx, DEF_TIM_VAL); + //SFCNOR_SET_SMP_DELAY(SFCNORx, SFC_DEV_CONF_SMP_DELAY_0); +} + +/** + * @brief set SFCNOR transfer registers + * @param SFCNORx pointer to a SFC_TypeDef structure that contains + * the sfc registers information. + * @param xfer sfc cdt configure value + * @param itmode interrupt mode flag + * @retval None + */ +void SFCNOR_SyncCdt(SFC_TypeDef *SFCNORx, struct sfc_cdt_xfer *xfer, int itmode) +{ + assert_param(IS_SFCNOR_INSTANCE(SFCNORx)); + assert_param(IS_SFCNOR_ITMODE(itmode)); + assert_param(IS_SFCNOR_CMD_INDEX(xfer->cmd_index)); + assert_param(IS_SFCNOR_DATAEN(xfer->dataen)); + assert_param(IS_SFCNOR_DATA_DIR(xfer->config.data_dir)); + assert_param(IS_SFCNOR_OPS_MODE(xfer->config.ops_mode)); + if (xfer->dataen) { + assert_param(IS_SFCNOR_DATALEN(xfer->config.datalen)); + } + + /* 1. set cmd index */ + MODIFY_REG(SFCNORx->CMD_IDX, SFC_CMD_IDX_CMD_IDX_Msk, xfer->cmd_index); + /* 2. set addr */ + WRITE_REG(SFCNORx->COL_ADDR, xfer->columnaddr); + WRITE_REG(SFCNORx->ROW_ADDR, xfer->rowaddr); + WRITE_REG(SFCNORx->STA_ADDR0, xfer->staaddr0); + WRITE_REG(SFCNORx->STA_ADDR1, xfer->staaddr1); + /* 3. config data config */ + MODIFY_REG(SFCNORx->CMD_IDX, SFC_CMD_IDX_CDT_DATA_EN_Msk, (xfer->dataen << SFC_CMD_IDX_CDT_DATA_EN_Pos)); + WRITE_REG(SFCNORx->TRAN_LEN, 0); + if (xfer->dataen) { + MODIFY_REG(SFCNORx->CMD_IDX, SFC_CMD_IDX_CDT_DIR_Msk, (xfer->config.data_dir << SFC_CMD_IDX_CDT_DIR_Pos)); + WRITE_REG(SFCNORx->TRAN_LEN, xfer->config.datalen); + /* Memory address for DMA when do not use DMA descriptor */ + WRITE_REG(SFCNORx->MEM_ADDR, 0); + + if (xfer->config.ops_mode == DMA_OPS) { + SFCNOR_SET_DMA_MODE(SFCNORx); +#if 1 + if (xfer->config.data_dir == GLB_TRAN_DIR_READ) { + InvalidateDCache_by_Addr((uint32_t *)xfer->config.buf, (uint32_t)(xfer->config.datalen)); + } else { + CleanInvalidateDCache_by_Addr((uint32_t *)xfer->config.buf, (uint32_t)(xfer->config.datalen)); + } +#endif + SFCNOR_SET_DESC_ADDR(SFCNORx, xfer->dmaDescAddr); + } else { + SFCNOR_SET_CPU_MODE(SFCNORx); + } + } + //SFCNOR_DumpReg(SFCNORx); + /* 4. start transfer */ + SFCNOR_CLEAR_ALL_INTC(SFCNORx); + if (!itmode) { + SFCNOR_MASK_ALL_INTC(SFCNORx); + } else { + SFCNOR_ENABLE_ALL_INTC(SFCNORx); + } + SFCNOR_TRIG_FLUSH(SFCNORx); + SFCNOR_TRIG_START(SFCNORx); +} /** * @} - */ + */ /** * @} - */ + */ diff --git a/drivers/drivers-x2600/include/board_eth_phy_conf.h b/projects/x2660-halley/Examples/icodec/include/board_eth_phy_conf.h similarity index 100% rename from drivers/drivers-x2600/include/board_eth_phy_conf.h rename to projects/x2660-halley/Examples/icodec/include/board_eth_phy_conf.h diff --git a/drivers/drivers-x2600/include/x2600_hal_conf.h b/projects/x2660-halley/Examples/icodec/include/x2600_hal_conf.h similarity index 96% rename from drivers/drivers-x2600/include/x2600_hal_conf.h rename to projects/x2660-halley/Examples/icodec/include/x2600_hal_conf.h index 2ca21f3a..bd304240 100644 --- a/drivers/drivers-x2600/include/x2600_hal_conf.h +++ b/projects/x2660-halley/Examples/icodec/include/x2600_hal_conf.h @@ -11,11 +11,6 @@ /* Hal Module selections. */ #define HAL_UART_ENABLED #define HAL_ADC_ENABLED -#define HAL_I2C_ENABLED -#define HAL_PWM_ENABLED -#define HAL_TCU_ENABLED -#define HAL_DPU_ENABLED -#define HAL_DPU_MIPI_ENABLED #define HAL_AIC_ENABLED #define HAL_SPI_ENABLED #define HAL_ICODEC_ENABLED @@ -26,6 +21,11 @@ #define HAL_EFUSE_ENABLED #define HAL_GMAC_ENABLED #define HAL_USB_ENABLED +#define HAL_I2C_ENABLED +#define HAL_PWM_ENABLED +#define HAL_TCU_ENABLED +#define HAL_DPU_ENABLED +#define HAL_DPU_MIPI_ENABLED #endif /* 系统时钟配配置,通过工具生成,随开发板或者平台变化.*/ @@ -38,17 +38,11 @@ #include "x2600_ll_cpm.h" #include "x2600_ll_gpio.h" #ifdef CORE_RISCV -#include "x2600_ll_risc_ccu.h" +//#include "x2600_ll_risc_ccu.h" #endif #include "x2600_hal_pdma.h" -//#include "x2600_hal_sfcnor.h" - -#ifdef HAL_MSC_ENABLED - -#endif - #ifdef HAL_DPU_ENABLED #include "x2600_hal_lcd.h" #endif @@ -58,6 +52,12 @@ #include "x2600_hal_mipi_dsi.h" #endif +#ifdef HAL_MSC_ENABLED +#endif + +#ifdef HAL_NOR_FLASH_ENABLED +#include "x2600_hal_sfc.h" +#endif #ifdef HAL_I2C_ENABLED #include "x2600_hal_i2c.h" diff --git a/drivers/drivers-x2600/include/x2600_sysclk_conf.h b/projects/x2660-halley/Examples/icodec/include/x2600_sysclk_conf.h similarity index 100% rename from drivers/drivers-x2600/include/x2600_sysclk_conf.h rename to projects/x2660-halley/Examples/icodec/include/x2600_sysclk_conf.h -- Gitee