// Copyright 2020-2021 Beken // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #pragma once #include #include "hal_port.h" #include "flash_hw.h" #include #ifdef __cplusplus extern "C" { #endif #define FLASH_LL_REG_BASE(_flash_unit_id) (SOC_FLASH_REG_BASE) static inline void flash_ll_soft_reset(flash_hw_t *hw) { hw->global_ctrl.soft_reset = 1; } static inline void flash_ll_init(flash_hw_t *hw) { flash_ll_soft_reset(hw); } static inline bool flash_ll_is_busy(flash_hw_t *hw) { return hw->op_ctrl.busy_sw; } static inline void flash_ll_wait_op_done(flash_hw_t *hw) { while (flash_ll_is_busy(hw)); } static inline uint32_t flash_ll_read_flash_id(flash_hw_t *hw) { return hw->rd_flash_id; } static inline void flash_ll_set_op_cmd(flash_hw_t *hw, flash_op_cmd_t cmd) { hw->op_cmd.op_type_sw = cmd; hw->op_ctrl.op_sw = 1; hw->op_ctrl.wp_value = 1; } static inline uint32_t flash_ll_get_id(flash_hw_t *hw) { flash_ll_set_op_cmd(hw, FLASH_OP_CMD_RDID); while (flash_ll_is_busy(hw)); return flash_ll_read_flash_id(hw); } static inline uint32_t flash_ll_get_mid(flash_hw_t *hw) { while (flash_ll_is_busy(hw)); hw->op_cmd.op_type_sw = FLASH_OP_CMD_RDID; hw->op_ctrl.op_sw = 1; while (flash_ll_is_busy(hw)); return flash_ll_read_flash_id(hw); } static inline void flash_ll_init_wrsr_cmd(flash_hw_t *hw, uint8_t wrsr_cmd) { hw->cmd_cfg.wrsr_cmd_reg = wrsr_cmd; hw->cmd_cfg.wrsr_cmd_sel = 1; flash_ll_wait_op_done(hw); } static inline void flash_ll_init_rdsr_cmd(flash_hw_t *hw, uint8_t rdsr_cmd) { hw->cmd_cfg.rdsr_cmd_reg = rdsr_cmd; hw->cmd_cfg.rdsr_cmd_sel = 1; flash_ll_wait_op_done(hw); } static inline void flash_ll_deinit_wrsr_cmd(flash_hw_t *hw) { hw->cmd_cfg.wrsr_cmd_reg = 0x1; hw->cmd_cfg.wrsr_cmd_sel = 0; flash_ll_wait_op_done(hw); } static inline void flash_ll_deinit_rdsr_cmd(flash_hw_t *hw) { hw->cmd_cfg.rdsr_cmd_reg = 0x5; hw->cmd_cfg.rdsr_cmd_sel = 0; flash_ll_wait_op_done(hw); } static inline void flash_ll_write_status_reg(flash_hw_t *hw, uint8_t sr_width, uint32_t sr_data) { while (flash_ll_is_busy(hw)); hw->config.wrsr_data = sr_data; while (flash_ll_is_busy(hw)); if (sr_width == 1) { flash_ll_set_op_cmd(hw, FLASH_OP_CMD_WRSR); } else if (sr_width == 2) { flash_ll_set_op_cmd(hw, FLASH_OP_CMD_WRSR2); } else { if(FLASH_ID_GD25Q32C == flash_ll_get_id(hw) || FLASH_ID_TH25Q64 == flash_ll_get_id(hw)) { flash_ll_set_op_cmd(hw, FLASH_OP_CMD_WRSR); while (flash_ll_is_busy(hw)); hw->config.wrsr_data = (sr_data >> LEN_WRSR_S0_S7); flash_ll_init_wrsr_cmd(hw, CMD_WRSR_S8_S15); // hw->op_ctrl.wp_value = 1; // ??? flash_ll_set_op_cmd(hw, FLASH_OP_CMD_WRSR); #if 0 while (flash_ll_is_busy(hw)); hw->config.wrsr_data = (sr_data >> LEN_WRSR_S8_S15); flash_ll_init_wrsr_cmd(hw, CMD_WRSR_S16_S24); flash_ll_set_op_cmd(hw, FLASH_OP_CMD_WRSR); #endif while (flash_ll_is_busy(hw)); // flash_ll_deinit_wrsr_cmd(hw); hw->cmd_cfg.v = 0; } else { flash_ll_set_op_cmd(hw, FLASH_OP_CMD_WRSR2); } } while (flash_ll_is_busy(hw)); } static inline void flash_ll_set_qe(flash_hw_t *hw, uint8_t qe_bit, uint8_t qe_bit_post) { hw->config.v |= qe_bit << qe_bit_post; } static inline uint32_t flash_ll_read_status_reg(flash_hw_t *hw, uint8_t sr_width) { uint32_t state_reg_data = 0; hw->cmd_cfg.v = 0; while (flash_ll_is_busy(hw)); flash_ll_set_op_cmd(hw, FLASH_OP_CMD_RDSR); while (flash_ll_is_busy(hw)); state_reg_data = hw->state.status_reg; if (sr_width ==1) return state_reg_data; flash_ll_set_op_cmd(hw, FLASH_OP_CMD_RDSR2); while (flash_ll_is_busy(hw)); state_reg_data |= hw->state.status_reg << 8; if (sr_width ==2) return state_reg_data; hw->cmd_cfg.rdsr_cmd_sel = 1; hw->cmd_cfg.rdsr_cmd_reg = 0x15; flash_ll_set_op_cmd(hw, FLASH_OP_CMD_RDSR); while (flash_ll_is_busy(hw)); state_reg_data |= hw->state.status_reg << 16; hw->cmd_cfg.v = 0; return state_reg_data; } static inline uint32_t flash_ll_get_crc_err_num(flash_hw_t *hw) { return (uint32_t)hw->state.crc_err_num; } static inline void flash_ll_enable_cpu_data_wr(flash_hw_t *hw) { hw->config.cpu_data_wr_en = 1; } static inline void flash_ll_disable_cpu_data_wr(flash_hw_t *hw) { hw->config.cpu_data_wr_en = 0; } static inline void flash_ll_clear_qwfr(flash_hw_t *hw) { hw->config.mode_sel = 0; hw->op_cmd.addr_sw_reg = 0; flash_ll_set_op_cmd(hw, FLASH_OP_CMD_CRMR); while (flash_ll_is_busy(hw)); } static inline void flash_ll_set_mode(flash_hw_t *hw, uint8_t mode_sel) { hw->config.mode_sel = mode_sel; } static inline void flash_ll_set_dual_mode(flash_hw_t *hw) { hw->config.mode_sel = FLASH_MODE_DUAL; } static inline void flash_ll_set_quad_m_value(flash_hw_t *hw, uint32_t m_value) { hw->state.m_value = m_value; } static inline void flash_ll_erase_block(flash_hw_t *hw, uint32_t erase_addr, int type) { while (flash_ll_is_busy(hw)); hw->op_cmd.addr_sw_reg = erase_addr; hw->op_cmd.op_type_sw = type; hw->op_ctrl.op_sw = 1; while (flash_ll_is_busy(hw)); } static inline void flash_ll_set_op_cmd_read(flash_hw_t *hw, uint32_t read_addr) { hw->op_cmd.addr_sw_reg = read_addr; hw->op_cmd.op_type_sw = FLASH_OP_CMD_READ; hw->op_ctrl.op_sw = 1; while (flash_ll_is_busy(hw)); } static inline uint32_t flash_ll_read_data(flash_hw_t *hw) { return hw->data_flash_sw; } static inline void flash_ll_set_op_cmd_write(flash_hw_t *hw, uint32_t write_addr) { hw->op_cmd.addr_sw_reg = write_addr; hw->op_cmd.op_type_sw = FLASH_OP_CMD_PP; hw->op_ctrl.op_sw = 1; while (flash_ll_is_busy(hw)); } static inline void flash_ll_write_data(flash_hw_t *hw, uint32_t data) { hw->data_sw_flash = data; } static inline void flash_ll_set_clk(flash_hw_t *hw, uint8_t clk_cfg) { hw->config.clk_cfg = clk_cfg; #if CONFIG_JTAG hw->config.crc_en = 0; #endif } static inline void flash_ll_set_default_clk(flash_hw_t *hw) { flash_ll_set_clk(hw, 0x5); } static inline void flash_ll_set_clk_dpll(flash_hw_t *hw) { hw->config.clk_cfg = 5; } static inline void flash_ll_set_clk_dco(flash_hw_t *hw, bool ate_enabled) { if (ate_enabled) { hw->config.clk_cfg = 0xB; } else { hw->config.clk_cfg = 0x9; } } static inline void flash_ll_write_enable(flash_hw_t *hw) { flash_ll_set_op_cmd(hw, FLASH_OP_CMD_WREN); while (flash_ll_is_busy(hw)); } static inline void flash_ll_write_disable(flash_hw_t *hw) { flash_ll_set_op_cmd(hw, FLASH_OP_CMD_WRDI); while (flash_ll_is_busy(hw)); } #ifdef __cplusplus } #endif