/* * Copyright (c) 2019-2023 Beijing Hanwei Innovation Technology Ltd. Co. and * its subsidiaries and affiliates (collectly called MKSEMI). * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form, except as embedded into an MKSEMI * integrated circuit in a product or a software update for such product, * must reproduce the above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or other materials * provided with the distribution. * * 3. Neither the name of MKSEMI nor the names of its contributors may be used * to endorse or promote products derived from this software without * specific prior written permission. * * 4. This software, with or without modification, must only be used with a * MKSEMI integrated circuit. * * 5. Any software provided in binary form under this license must not be * reverse engineered, decompiled, modified and/or disassembled. * * THIS SOFTWARE IS PROVIDED BY MKSEMI "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL MKSEMI OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef MK_FLASH_H_ #define MK_FLASH_H_ #include "mk_common.h" #include "mk_dma.h" #include "mk_misc.h" #ifndef FLASH_INT_MODE_EN #define FLASH_INT_MODE_EN (1) #endif #ifndef FLASH_DMA_MODE_EN #define FLASH_DMA_MODE_EN (1) #endif #ifndef FLASH_WRITE_EN #define FLASH_WRITE_EN (1) #endif /** * @addtogroup MK8000_Flash * @{ */ #define FLASH_PAGE_SIZE 0x100U #define FLASH_SECTOR_SIZE 0x1000U #define FLASH_BLOCK_SIZE 0x10000U #define FLASH_OP_ERASE 1 #define FLASH_OP_WRITE 2 #define FLASH_OP_READ 3 // Flash status check timeout #define FLASH_OP_ERASE_SECTOR_TIMEOUT __MS_TO_TICKS(600) #define FLASH_OP_ERASE_BLOCK_TIMEOUT __MS_TO_TICKS(4000) #define FLASH_OP_WRITE_PAGE_TIMEOUT __MS_TO_TICKS(6) #define FLASH_OP_WRITE_STATUS_TIMEOUT __MS_TO_TICKS(40) /** FLASH device instance */ enum FLASH_DEV_T { FLASH_ID0 = 0, FLASH_MAX_NUM }; /** FLASH operation code */ enum FLASH_OPCODE_T { FLASH_OPCODE_READ = 0, FLASH_OPCODE_PROGRAM_PAGE, FLASH_OPCODE_GET_STATUS, FLASH_OPCODE_GET_STATUS1, FLASH_OPCODE_ERASE_SECTOR, FLASH_OPCODE_ERASE_BLOCK, FLASH_OPCODE_WRITE_ENABLE, FLASH_OPCODE_WRITE_REGISTER, FLASH_OPCODE_RDID, FLASH_OPCODE_POWER_DOWN, FLASH_OPCODE_RELEASE_POWER_DOWN, FLASH_OPCODE_NUM, }; /** FLASH operation state */ enum FLASH_STATE_T { FLASH_STATE_RESET = 0, FLASH_STATE_READY, FLASH_STATE_BUSY_READ, FLASH_STATE_BUSY_ERASE, FLASH_STATE_BUSY_WRITE, FLASH_STATE_TIMEOUT, FLASH_STATE_ERROR }; /*! @brief FLASH data direction */ enum FLASH_DATA_DIR_TYPE_T { FLASH_DATA_IN = 0x0U, /*!< Data input from serial flash. */ FLASH_DATA_OUT = 0x1U /*!< Data output to serial flash. */ }; /*! @brief FLASH command opcode format */ enum FLASH_CMD_FORMAT_T { FLASH_CMD_ALL_SERIAL = 0x0, /*!< All fields of command are serial. */ FLASH_CMD_DATA_QUAD_DUAL = 0x1U, /*!< Only data field is dual/quad, others are serial. */ FLASH_CMD_OP_SERIAL = 0x2U, /*!< Only opcode field is serial, others are quad/dual. */ FLASH_CMD_ALL_QUAD_DUAL = 0x3U /*!< All fields of command are dual/quad mode. */ }; /*! @brief FLASH command type */ enum FLASH_CMD_TYPE_T { FLASH_CMD_OP_ONLY = 0x1U, /*!< Command only have opcode, no address field */ FLASH_CMD_OP_ADDR_1B = 0x2U, /*!< Command have opcode and also one byte address field */ FLASH_CMD_OP_ADDR_2B = 0x3U, /*!< Command have opcode and also two bytes address field */ FLASH_CMD_OP_ADDR_3B = 0x4U, /*!< Command have opcode and also three bytes address field. */ FLASH_CMD_OP_ADDR_4B = 0x5U, /*!< Command have opcode and also four bytes address field */ FLASH_CMD_NO_OP_ADDR_3B = 0x6U, /*!< Command have no opcode and three bytes address field */ FLASH_CMD_NO_OP_ADDR_4B = 0x7U /*!< Command have no opcode and four bytes address field */ }; /*! @brief FLASH command structure */ struct FLASH_CMD_T { uint32_t polling_mode; /*!< For command need to read data from serial flash */ enum FLASH_DATA_DIR_TYPE_T data_dir; /*!< Data direction of this command. */ enum FLASH_CMD_FORMAT_T format; /*!< Command format */ enum FLASH_CMD_TYPE_T type; /*!< Command type */ uint16_t data_len; /*!< How many data bytes are needed in this command. */ uint8_t dummy_len; /*!< How many intermediate bytes needed */ uint8_t opcode; /*!< Command opcode value */ }; /*! * @brief FLASH configuration structure. */ struct FLASH_CFG_T { uint16_t timeout; /*!< SPI transfer timeout, the unit is SCK cycles */ uint8_t cs_high_time; /*!< CS high time cycles */ bool dual_mode : 1; /*!< true: dual mode, false: quad mode */ bool prefetch_dis : 1; /*!< True means FLASH will not attempt a speculative prefetch */ bool cache_prefetch_dis : 1; /*!< Disable prefetch of cache line */ bool feedback_clk_sel : 1; /*!< Is data sample uses feedback clock */ bool spi_sck_high : 1; /*!< FLASH spi mode select */ bool spi_falling_edge_active : 1; /*!< If enable read full clock cycle. */ bool dma_en : 1; bool int_en : 1; uint32_t start_addr; uint32_t total_size; uint32_t block_size; uint16_t sector_size; uint16_t page_size; }; struct FLASH_DMA_OP_CFG_T { uint32_t start_addr; const uint8_t *buf; uint32_t len; uint32_t count; }; struct FLASH_WRITE_NBYTES_CFG_T { const uint8_t *src_addr; uint32_t write_start_addr; uint32_t write_end_addr; uint32_t offset_addr; uint32_t page_start; uint32_t page_end; uint32_t page_count; uint32_t write_num; uint32_t write_count; uint32_t start_page_inc_data_len; uint32_t end_page_inc_data_len; uint32_t src_buf_pos; __IOM uint32_t dest_tmp_addr; }; struct FLASH_HANDLE_T { FLASH_CTRL_TypeDef *const base; const IRQn_Type irq; enum DMA_CH_T dma_wr_ch; enum DMA_CH_T dma_rd_ch; enum FLASH_STATE_T state; struct FLASH_CFG_T config; struct FLASH_WRITE_NBYTES_CFG_T wr_nbyte_cfg; struct FLASH_DMA_OP_CFG_T dma_op; uint32_t code; // reserved | err_code | int_flag | op_code drv_callback_t callback; uint8_t flash_type; uint8_t wrsr_type; uint8_t work_mode; uint8_t promote_fclk; uint8_t is_open; }; #ifdef __cplusplus extern "C" { #endif extern struct FLASH_HANDLE_T flash_handle[FLASH_MAX_NUM]; int flash_open(enum FLASH_DEV_T id, struct FLASH_CFG_T *cfg); int flash_close(enum FLASH_DEV_T id); void RAM_FUNC flash_power_up(enum FLASH_DEV_T id); void RAM_FUNC flash_power_down(enum FLASH_DEV_T id); int flash_sector_erase(enum FLASH_DEV_T id, uint32_t sector); int flash_block_erase(enum FLASH_DEV_T id, uint32_t block); int flash_erase(enum FLASH_DEV_T id, uint32_t start_addr, uint32_t len); int flash_write_nbytes(enum FLASH_DEV_T id, uint32_t start_addr, const uint8_t *buf, uint32_t len); int flash_write(enum FLASH_DEV_T id, uint32_t start_addr, const uint8_t *buf, uint32_t len); int flash_read(enum FLASH_DEV_T id, uint32_t start_addr, uint8_t *buf, uint32_t len); void FLASH_CTRL_IRQHandler(void); bool flash_check_busy(enum FLASH_DEV_T id); int RAM_FUNC flash_open_for_xip(enum FLASH_DEV_T id); #ifdef __cplusplus } #endif /** * @} */ #endif /* MK_FLASH_H_ */