/**************************************************************************** * * Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED. * * This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT * be copied by any method or incorporated into another program without * the express written consent of Aerospace C.Power. This Information or any portion * thereof remains the property of Aerospace C.Power. The Information contained herein * is believed to be accurate and Aerospace C.Power assumes no responsibility or * liability for its use in any way and conveys no license or title under * any patent or copyright and makes no representation or warranty that this * Information is free from patent or copyright infringement. * * ****************************************************************************/ #include "os_types.h" #include "chip_reg_base.h" #include "hw_reg_api.h" #include "efuse_dig_reg.h" #include "efuse_dig_reg_s.h" #include "apb.h" #include "efuse.h" #include "efuse_mapping.h" #include "iot_errno.h" #include "iot_system.h" #include "iot_utils_api.h" #define EFUSE_WAIT_IDLE_TIMEOUT_CNT 10000000 /** * efuse cmd **/ typedef enum { EFUSE_CMD_PHY_BIT_PROG = 0x00, EFUSE_CMD_PHY_BYTE_READ, EFUSE_CMD_PHY_MUL_BYTE_LOAD, EFUSE_CMD_REG_BYTE_READ, EFUSE_CMD_REG_BYTE_WRITE, EFUSE_CMD_MAX } EFUSE_CMD; static volatile efuse_ctrl_reg_t *efuse_base = (volatile efuse_ctrl_reg_t *)EFUSE_BASEADDR; void efuse_init(void) { /* enable apb clock */ apb_enable(APB_EFUSE); /* kl3 after power on, eFuse data will be automatically loaded into the * internal register, so manual loading is not required. */ } void efuse_deinit(void) { /* disable apb clock */ apb_disable(APB_EFUSE); } uint8_t efuse_get_idle_statue(void) { /* idle is 1 */ return RE_REG_FIELD(efuse_base->efuse_idle, efuse_idle); } void efuse_wait_ilde_vaild(void) { uint32_t timer_cnt = 0; while (!efuse_get_idle_statue()) { __asm volatile("nop\n"); if (timer_cnt++ > EFUSE_WAIT_IDLE_TIMEOUT_CNT) { IOT_ASSERT(0); } } } void efuse_set_bit_addr(uint8_t efuse_byte_num, uint8_t bit_index) { /* efuse addr: byte for number: [15:0], bit for byte: [31:16] */ WR_REG_FIELD(efuse_base->efuse_bit_addr, efuse_bit_addr_x, efuse_byte_num); WR_REG_FIELD(efuse_base->efuse_bit_addr, efuse_bit_addr_y, bit_index); } void efuse_set_read_len(uint16_t len) { efuse_base->efuse_len_read.w = (uint32_t)len; } void efuse_enable_cmd_set_mode(uint8_t mode) { IOT_ASSERT(mode < EFUSE_CMD_MAX); WR_REG_FIELD(efuse_base->efuse_cmd, efuse_cmd, mode); /* enable command vaild */ WR_REG_FIELD(efuse_base->efuse_cmd, efuse_cmd_valid, 1); } uint16_t efuse_read_bit_ecnt(void) { return (uint16_t)efuse_base->efuse_status.w; } uint32_t efuse_read_reg(void) { return efuse_base->efuse_reg_read.w; } void efuse_write_reg(uint8_t data) { efuse_base->efuse_reg_write.w = (uint32_t)data; } uint32_t efuse_read_phy(void) { return efuse_base->efuse_phy_read.w; } uint32_t efuse_get_tpg() { return (uint32_t)RE_REG_FIELD(efuse_base->efuse_tpg, efuse_tpg); } void efuse_phy_bit_prog(uint8_t efuse_byte_num, uint8_t bit_index) { /* only opeation when efuse is in idle status */ efuse_wait_ilde_vaild(); efuse_set_bit_addr(efuse_byte_num, bit_index); efuse_enable_cmd_set_mode(EFUSE_CMD_PHY_BIT_PROG); efuse_wait_ilde_vaild(); } uint8_t efuse_phy_byte_read(uint8_t efuse_byte_num) { /* only opeation when efuse is in idle status */ efuse_wait_ilde_vaild(); /* bit_index set to 0 when read the entire Byte */ efuse_set_bit_addr(efuse_byte_num, 0); efuse_enable_cmd_set_mode(EFUSE_CMD_PHY_BYTE_READ); efuse_wait_ilde_vaild(); return (uint8_t)efuse_read_phy(); } void efuse_phy_load_to_reg(uint32_t offset, uint32_t len) { /* only opeation when efuse is in idle status */ efuse_wait_ilde_vaild(); /* bit_index set to 0 when read the entire Byte */ efuse_set_bit_addr(offset, 0); efuse_set_read_len(len); efuse_enable_cmd_set_mode(EFUSE_CMD_PHY_MUL_BYTE_LOAD); efuse_wait_ilde_vaild(); } void efuse_reg_byte_prog(uint8_t efuse_byte_num, uint8_t data) { /* only opeation when efuse is in idle status */ efuse_wait_ilde_vaild(); efuse_set_bit_addr(efuse_byte_num, 0); efuse_write_reg(data); efuse_enable_cmd_set_mode(EFUSE_CMD_REG_BYTE_WRITE); efuse_wait_ilde_vaild(); } uint8_t efuse_reg_byte_read(uint8_t efuse_byte_num) { /* only opeation when efuse is in idle status */ efuse_wait_ilde_vaild(); /* bit_index set to 0 when read the entire Byte */ efuse_set_bit_addr(efuse_byte_num, 0); efuse_enable_cmd_set_mode(EFUSE_CMD_REG_BYTE_READ); efuse_wait_ilde_vaild(); return (uint8_t)efuse_read_reg(); } static uint32_t efuse_read_bytes(uint32_t offset, uint8_t len, uint8_t *p) { for (uint8_t i = 0; i < len; i++) { p[i] = efuse_reg_byte_read(offset + i); } return 0; } uint32_t efuse_read(uint32_t offset) { /* compatible with bootram and ram program, read out 4 bytes */ uint32_t value = 0; for (int i = 3; i >= 0; i--) { value = (value << 8) + efuse_reg_byte_read(i + offset); } return value; } uint32_t efuse_write_bytes(uint32_t offset, uint8_t len, uint8_t *val_ptr) { for (uint8_t i = 0; i < len; i++) { /* write in 1 bytes */ uint8_t val = *(val_ptr + i); for (uint8_t j = 0; j < 8; j++) { if (val & (1 << j)) { efuse_phy_bit_prog(offset + i, j); } } } /* reload phy value to reg */ efuse_phy_load_to_reg(offset, len); return 0; } uint32_t efuse_write(uint32_t offset, uint32_t val) { /* compatible with bootram and ram program, write in 4 bytes */ uint8_t temp = 0; for (uint8_t i = 0; i < 4; i++) { temp = (uint8_t)(val >> (i * 8)); for (uint8_t j = 0; j < 8; j++) { if (temp & (1 << j)) { efuse_phy_bit_prog(offset + i, j); } } } /* reload phy value to reg */ efuse_phy_load_to_reg(offset, sizeof(uint32_t)); return 0; } /* efuse data read and write function, kl3 private */ /* only part of the API is provided for use by ATE programs */ uint32_t efuse_get_lot_id(uint8_t *buf) { uint8_t index = CFG_EFUSE_MAPPING_ATE_SECTION_W0_ADDR; if (buf == NULL) { return ERR_FAIL; } for (uint8_t i = 0; i < 6; i++) { buf[i] = efuse_reg_byte_read(index + i); } return ERR_OK; } uint32_t efuse_get_wafer_id() { uint8_t index = CFG_EFUSE_MAPPING_ATE_SECTION_W1_ADDR + (EFUSE_FUNC_ATE_WAFER_ID_OFFSET >> 3); return efuse_reg_byte_read(index); } uint32_t efuse_get_die_x_coordinate() { uint8_t index = CFG_EFUSE_MAPPING_ATE_SECTION_W1_ADDR + (EFUSE_FUNC_ATE_DIE_X_COORDINATE_OFFSET >> 3); return efuse_reg_byte_read(index); } uint32_t efuse_get_die_y_coordinate() { uint8_t index = CFG_EFUSE_MAPPING_ATE_SECTION_W2_ADDR + (EFUSE_FUNC_ATE_DIE_Y_COORDINATE_OFFSET >> 3); return efuse_reg_byte_read(index); } uint32_t efuse_get_wafer_rev_record() { uint8_t index = CFG_EFUSE_MAPPING_ATE_SECTION_W2_ADDR + (EFUSE_FUNC_ATE_WAFER_REV_RECORD_OFFSET >> 3); return efuse_reg_byte_read(index); } uint32_t efuse_get_ft_pass_flag(void) { uint8_t index = CFG_EFUSE_MAPPING_ATE_SECTION_W2_ADDR + (EFUSE_FUNC_ATE_FT_PASS_FLAG_OFFSET >> 3); return (efuse_reg_byte_read(index) & 0xf); } uint32_t efuse_get_analog_bin_ver(void) { uint8_t index = CFG_EFUSE_MAPPING_ATE_SECTION_W2_ADDR + (EFUSE_FUNC_ATE_ANALOG_BIN_VER_OFFSET >> 3); return (efuse_reg_byte_read(index) >> 4); } uint8_t efuse_get_dcdc_trim(void) { uint8_t index = CFG_EFUSE_MAPPING_ATE_SECTION_W2_ADDR + (EFUSE_FUNC_ATE_D_VREF_TUNE_DCDC_OFFSET >> 3); return (efuse_reg_byte_read(index) & 0xf); } uint32_t efuse_get_flash_ldo_out_trim(void) { uint8_t index = CFG_EFUSE_MAPPING_ATE_SECTION_W2_ADDR + (EFUSE_FUNC_ATE_FLASH_LDO_OUT_TRIM_18_OFFSET >> 3); return (efuse_reg_byte_read(index) >> 4); } uint32_t efuse_set_flash_ldo_out_trim(ate_ldo_value_e ldo_value) { uint8_t ldo_value_temp; uint8_t index = CFG_EFUSE_MAPPING_ATE_SECTION_W2_ADDR + (EFUSE_FUNC_ATE_FLASH_LDO_OUT_TRIM_18_OFFSET >> 3); if (ldo_value >= ATE_LDO_MAX || ldo_value < 0) { return ERR_FAIL; } ldo_value_temp = efuse_reg_byte_read(index) | (ldo_value << 4); efuse_write_bytes(index, 1, &ldo_value_temp); return ERR_OK; } uint32_t efuse_get_d_mdll_ldo_vref_trim(void) { uint8_t index = CFG_EFUSE_MAPPING_ATE_SECTION_W3_ADDR + (EFUSE_FUNC_ATE_D_MDLL_LDOVREF_TRIM_OFFSET >> 3); return (efuse_reg_byte_read(index) & 0xf); } uint32_t efuse_get_d_bg_vbg_cntl(void) { uint8_t index = CFG_EFUSE_MAPPING_ATE_SECTION_W3_ADDR + (EFUSE_FUNC_ATE_D_BG_VBG_CNTL_OFFSET >> 3); return ((efuse_reg_byte_read(index) >> 4) & 0x7); } uint32_t efuse_get_d_bg_iccal(void) { uint8_t index = CFG_EFUSE_MAPPING_ATE_SECTION_W3_ADDR + (EFUSE_FUNC_ATE_D_BG_ICCAL_OFFSET >> 3); return (efuse_reg_byte_read(index) & 0x1f); } uint32_t efuse_get_rx_adc_vcm_ctrl(void) { uint8_t index = CFG_EFUSE_MAPPING_ATE_SECTION_W3_ADDR + (EFUSE_FUNC_ATE_RX_ADC_VCM_CTRL_OFFSET >> 3); return ((efuse_reg_byte_read(index) >> 5) & 0x7); } uint32_t efuse_get_flash_ldo_out_trim_2v5(void) { uint8_t index = CFG_EFUSE_MAPPING_ATE_SECTION_W3_ADDR + (EFUSE_FUNC_ATE_FLASH_LDO_OUT_TRIM_25_OFFSET >> 3); return (efuse_reg_byte_read(index) & 0xf); } uint16_t efuse_get_sadc_meter_dc_offset_code(void) { uint8_t byte_index; uint16_t value = 0; byte_index = CFG_EFUSE_MAPPING_SADC_SECTION_W30_ADDR + (EFUSE_FUNC_SADC_METER_DC_OFFSET_OFFSET >> 3); efuse_read_bytes(byte_index, sizeof(value), (uint8_t*)&value); return value; } uint16_t efuse_get_sadc_meter_dc_offset_code_n12db(void) { uint8_t byte_index; uint16_t value = 0; byte_index = CFG_EFUSE_MAPPING_SADC_2_SECTION_W26_ADDR + (EFUSE_FUNC_SADC_2_METER_DC_OFFSET_N12DB_OFFSET >> 3); efuse_read_bytes(byte_index, sizeof(value), (uint8_t*)&value); return value; } uint16_t efuse_get_sadc_meter_dc_offset_code_n6db(void) { uint8_t byte_index; uint16_t value = 0; byte_index = CFG_EFUSE_MAPPING_SADC_2_SECTION_W26_ADDR + (EFUSE_FUNC_SADC_2_METER_DC_OFFSET_N6DB_OFFSET >> 3); efuse_read_bytes(byte_index, sizeof(value), (uint8_t*)&value); return value; } uint16_t efuse_get_sadc_meter_dc_offset_code_12db(void) { uint8_t byte_index; uint16_t value = 0; byte_index = CFG_EFUSE_MAPPING_SADC_2_SECTION_W27_ADDR + (EFUSE_FUNC_SADC_2_METER_DC_OFFSET_12DB_OFFSET >> 3); efuse_read_bytes(byte_index, sizeof(value), (uint8_t*)&value); return value; } uint16_t efuse_get_sadc_meter_dc_offset_code_24db(void) { uint8_t byte_index; uint16_t value = 0; byte_index = CFG_EFUSE_MAPPING_SADC_2_SECTION_W27_ADDR + (EFUSE_FUNC_SADC_2_METER_DC_OFFSET_24DB_OFFSET >> 3); efuse_read_bytes(byte_index, sizeof(value), (uint8_t*)&value); return value; } uint16_t efuse_get_sadc_meter_vref_code(void) { uint8_t byte_index; uint16_t value = 0; byte_index = CFG_EFUSE_MAPPING_SADC_SECTION_W31_ADDR + (EFUSE_FUNC_SADC_METER_VREF_OFFSET >> 3); efuse_read_bytes(byte_index, sizeof(value), (uint8_t*)&value); return value; } uint16_t efuse_get_sadc_meter_vcm_code(void) { uint8_t byte_index; uint16_t value = 0; byte_index = CFG_EFUSE_MAPPING_SADC_SECTION_W31_ADDR + (EFUSE_FUNC_SADC_METER_VCM_OFFSET >> 3); efuse_read_bytes(byte_index, sizeof(value), (uint8_t*)&value); return value; } uint16_t efuse_get_sadc_tpid_dc_offset_code(void) { uint8_t byte_index; uint16_t value = 0; byte_index = CFG_EFUSE_MAPPING_SADC_SECTION_W29_ADDR + (EFUSE_FUNC_SADC_TPID_DC_OFFSET_OFFSET >> 3); efuse_read_bytes(byte_index, sizeof(value), (uint8_t*)&value); return value; } uint16_t efuse_get_sadc_tpid_dc_offset_code_n12db(void) { uint8_t byte_index; uint16_t value = 0; byte_index = CFG_EFUSE_MAPPING_SADC_2_SECTION_W24_ADDR + (EFUSE_FUNC_SADC_2_TPID_DC_OFFSET_N12DB_OFFSET >> 3); efuse_read_bytes(byte_index, sizeof(value), (uint8_t*)&value); return value; } uint16_t efuse_get_sadc_tpid_dc_offset_code_n6db(void) { uint8_t byte_index; uint16_t value = 0; byte_index = CFG_EFUSE_MAPPING_SADC_2_SECTION_W24_ADDR + (EFUSE_FUNC_SADC_2_TPID_DC_OFFSET_N6DB_OFFSET >> 3); efuse_read_bytes(byte_index, sizeof(value), (uint8_t*)&value); return value; } uint16_t efuse_get_sadc_tpid_dc_offset_code_12db(void) { uint8_t byte_index; uint16_t value = 0; byte_index = CFG_EFUSE_MAPPING_SADC_2_SECTION_W25_ADDR + (EFUSE_FUNC_SADC_2_TPID_DC_OFFSET_12DB_OFFSET >> 3); efuse_read_bytes(byte_index, sizeof(value), (uint8_t*)&value); return value; } uint16_t efuse_get_sadc_tpid_dc_offset_code_24db(void) { uint8_t byte_index; uint16_t value = 0; byte_index = CFG_EFUSE_MAPPING_SADC_2_SECTION_W25_ADDR + (EFUSE_FUNC_SADC_2_TPID_DC_OFFSET_24DB_OFFSET >> 3); efuse_read_bytes(byte_index, sizeof(value), (uint8_t*)&value); return value; } uint16_t efuse_get_sadc_tpid_vref_code(void) { uint8_t byte_index; uint16_t value = 0; byte_index = CFG_EFUSE_MAPPING_SADC_SECTION_W29_ADDR + (EFUSE_FUNC_SADC_TPID_VREF_OFFSET >> 3); efuse_read_bytes(byte_index, sizeof(value), (uint8_t*)&value); return value; } uint16_t efuse_get_sadc_tpid_vcm_code(void) { uint8_t byte_index; uint16_t value = 0; byte_index = CFG_EFUSE_MAPPING_SADC_SECTION_W30_ADDR + (EFUSE_FUNC_SADC_TPID_VCM_OFFSET >> 3); efuse_read_bytes(byte_index, sizeof(value), (uint8_t*)&value); return value; } void efuse_get_mac_addr(uint8_t *mac) { if (mac == NULL) { return; } #if HW_PLATFORM > HW_PLATFORM_FPGA uint8_t index = CFG_EFUSE_MAPPING_ATE_SECTION_W4_ADDR + (EFUSE_FUNC_ATE_MAC_ADDR0_OFFSET >> 3); /* mac addr len=6 */ for (uint8_t i = 0; i < 6; i++) { mac[i] = efuse_reg_byte_read(index + i); } #endif } void efuse_set_mac_addr(uint8_t *mac) { uint32_t index = CFG_EFUSE_MAPPING_ATE_SECTION_W4_ADDR + (EFUSE_FUNC_ATE_MAC_ADDR0_OFFSET >> 3); /* mac addr len=6 */ efuse_write_bytes(index, 6, mac); } void efuse_set_chip_id(uint32_t chipid) { /* | chid_id[15:12] | chip_id[11:8] | chip_id[7:4] | chip_id[3:0] | * | project[3:0] | wafer[3:0] | mark[3:0] | sip[3:0] | */ uint32_t chipid_w = (((chipid >> 4) & 0xFF) | ((chipid & 0xF) << 8) | ((chipid & 0xF000))) & 0xFFFF; uint32_t index = CFG_EFUSE_MAPPING_ATE_SECTION_W3_ADDR + (EFUSE_FUNC_MARK_OFFSET >> 3); /* chip id: [15:12] wafer_version [11:8] mark [7:0] sip */ efuse_write_bytes(index, 2, (uint8_t *)&chipid_w); } uint32_t efuse_get_chip_id(void) { #if HW_PLATFORM > HW_PLATFORM_FPGA uint32_t chipid = 0; uint8_t byte_index; uint8_t mark_and_wafer, sip_and_project; /* | chid_id[15:12] | chip_id[11:8] | chip_id[7:4] | chip_id[3:0] | * | project[3:0] | wafer[3:0] | mark[3:0] | sip[3:0] | */ byte_index = CFG_EFUSE_MAPPING_ATE_SECTION_W3_ADDR + (EFUSE_FUNC_MARK_OFFSET >> 3); mark_and_wafer = efuse_reg_byte_read(byte_index); byte_index = CFG_EFUSE_MAPPING_ATE_SECTION_W4_ADDR + (EFUSE_FUNC_SIP_OFFSET >> 3); sip_and_project = efuse_reg_byte_read(byte_index); chipid = ((sip_and_project & 0xF0) << 8) | (mark_and_wafer << 4) | (sip_and_project & 0xF); return chipid & 0xFFFF; #else return CHIP_ID_HZ3211_V1A; #endif } /* about efuse_set_sub_id: * 1.这个函数只应该被 ram.bin 调用; * 2.ate efuse内容检查是不检查sub id的值; * 3.上层应用,sub id和chip id会被使用. * 底层应用,sub id不牵扯任何芯片资源; */ void efuse_set_sub_id(uint32_t subid) { /* | sub_id[15:12] | sub_id[11:8] | sub_id[7:4] | sub_id[3:0] | * | project[3:0] | wafer[3:0] | mark[3:0] | sip[3:0] | */ uint32_t subid_w = (((subid >> 4) & 0xFF) | ((subid & 0xF) << 8) | ((subid & 0xF000))) & 0xFFFF; uint32_t index = CFG_EFUSE_MAPPING_PATCH_SECTION_W28_ADDR + (EFUSE_FUNC_PATCH_SUB_MARK_OFFSET >> 3); /* sub id: [15:12] wafer_version [11:8] mark [7:0] sip */ efuse_write_bytes(index, 2, (uint8_t *)&subid_w); } uint32_t efuse_get_sub_id(void) { #if HW_PLATFORM > HW_PLATFORM_FPGA uint32_t subid = 0; uint8_t byte_index; uint8_t mark_and_wafer, sip_and_project; /* | sub_id[15:12] | sub_id[11:8] | sub_id[7:4] | sub_id[3:0] | * | project[3:0] | wafer[3:0] | mark[3:0] | sip[3:0] | */ byte_index = CFG_EFUSE_MAPPING_PATCH_SECTION_W28_ADDR + (EFUSE_FUNC_PATCH_SUB_MARK_OFFSET >> 3); mark_and_wafer = efuse_reg_byte_read(byte_index); byte_index = CFG_EFUSE_MAPPING_PATCH_SECTION_W28_ADDR + (EFUSE_FUNC_PATCH_SUB_SIP_OFFSET >> 3); sip_and_project = efuse_reg_byte_read(byte_index); subid = ((sip_and_project & 0xF0) << 8) | (mark_and_wafer << 4) | (sip_and_project & 0xF); return subid & 0xFFFF; #else return CHIP_ID_HZ3211_V1A; #endif } void efuse_get_sadc_calib_code(uint8_t id, float *vref, float *vcm, float *dc_offset, uint8_t dc_offset_array_len) { if (dc_offset_array_len < 5) { return; } if (id == 0) { //meter if (dc_offset) { /* the order is the same as sadc_hw_calib_gain_t */ dc_offset[0] = (float)efuse_get_sadc_meter_dc_offset_code_n12db(); dc_offset[1] = (float)efuse_get_sadc_meter_dc_offset_code_n6db(); dc_offset[2] = (float)efuse_get_sadc_meter_dc_offset_code(); dc_offset[3] = (float)efuse_get_sadc_meter_dc_offset_code_12db(); dc_offset[4] = (float)efuse_get_sadc_meter_dc_offset_code_24db(); } if (vref) { *vref = (float)efuse_get_sadc_meter_vref_code(); } if (vcm) { *vcm = (float)efuse_get_sadc_meter_vcm_code(); } } else if (id == 1) { //tpid if (dc_offset) { /* the order is the same as sadc_hw_calib_gain_t */ dc_offset[0] = (float)efuse_get_sadc_tpid_dc_offset_code_n12db(); dc_offset[1] = (float)efuse_get_sadc_tpid_dc_offset_code_n6db(); dc_offset[2] = (float)efuse_get_sadc_tpid_dc_offset_code(); dc_offset[3] = (float)efuse_get_sadc_tpid_dc_offset_code_12db(); dc_offset[4] = (float)efuse_get_sadc_tpid_dc_offset_code_24db(); } if (vref) { *vref = (float)efuse_get_sadc_tpid_vref_code(); } if (vcm) { *vcm = (float)efuse_get_sadc_tpid_vcm_code(); } } else { /* do nothing */ } /* efuse saves the sampling values that retain 2 decimal place */ *vref /= EFUSE_SADC_SAMPLING_CODE_MULTIPLE; *vcm /= EFUSE_SADC_SAMPLING_CODE_MULTIPLE; for (uint8_t i = 0; i < 5; i++) { dc_offset[i] /= EFUSE_SADC_SAMPLING_CODE_MULTIPLE; } } uint32_t efuse_get_rf_tx_iqm_dc_calib_info(uint8_t *i_mag, uint8_t *q_mag, uint8_t *i_phase, uint8_t *q_phase, int8_t *i_dc, int8_t *q_dc) { efuse_section_ana_t ana = {0}; uint32_t index = CFG_EFUSE_MAPPING_SYS_ANA_SECTION_W10_ADDR + (EFUSE_FUNC_ANA_DATA0_OFFSET >> 3); efuse_read_bytes(index, sizeof(ana), (uint8_t *)&ana); if (ana.valid_mark & EFULSE_SEC_ANA_VALID_MARK_RF_TX_IQM_DC_CALIB) { *i_mag = ana.tx_iqm_dc.i_mag; *q_mag = ana.tx_iqm_dc.q_mag; *i_phase = ana.tx_iqm_dc.i_phase; *q_phase = ana.tx_iqm_dc.q_phase; *i_dc = ana.tx_iqm_dc.i_dc; *q_dc = ana.tx_iqm_dc.i_dc; return ERR_OK; } return ERR_NOT_EXIST; } /*******BOND FUNCTION BEGIN********/ uint32_t efuse_set_bond_data(uint32_t bond_data) { uint32_t byte_index; uint32_t bond_data_tmp; bond_data_tmp = (efuse_read(CFG_EFUSE_MAPPING_BOND_SECTION_W6_ADDR) & efuse_read(CFG_EFUSE_MAPPING_BOND_SECTION_W7_ADDR)) | bond_data; byte_index = CFG_EFUSE_MAPPING_BOND_SECTION_W6_ADDR; efuse_write(byte_index, bond_data_tmp); byte_index = CFG_EFUSE_MAPPING_BOND_SECTION_W7_ADDR; efuse_write(byte_index, bond_data_tmp); return 0; } uint32_t efuse_get_bond_data(bond_type type) { uint32_t ret_data; uint32_t bond_data, bond_data_backup; switch (type) { case BOND_CONFIG: bond_data = efuse_read(CFG_EFUSE_MAPPING_BOND_SECTION_W6_ADDR); ret_data = bond_data; break; case BOND_BACKUP: bond_data_backup = efuse_read(CFG_EFUSE_MAPPING_BOND_SECTION_W7_ADDR); ret_data = bond_data_backup; break; case BOND_DATA: default: bond_data = efuse_read(CFG_EFUSE_MAPPING_BOND_SECTION_W6_ADDR); bond_data_backup = efuse_read(CFG_EFUSE_MAPPING_BOND_SECTION_W7_ADDR); ret_data = bond_data & bond_data_backup; break; } return ret_data; } /*******BOND FUNCTION END********/ /* efuse data read and write function, kl public */ uint8_t efuse_check_data() { /* 0x00: check succeed; other: the corresponding item fails to be verified. * bit 0: chip id check result; * bit 1: mac address check result; * bit 2: ate calibration check result; * bit 3: sadc meter check result. * bit 4: sadc tpid check result. */ uint8_t ret_st = 0x00; #if HW_PLATFORM > HW_PLATFORM_FPGA uint32_t ate_info, chipid, ate_ver; uint8_t mac_info[IOT_MAC_ADDR_LEN] = {0}; uint8_t i = 0; /* check chip id */ chipid = efuse_get_chip_id(); if (chipid == 0) { ret_st |= 1 << 0; } /* check mac */ efuse_get_mac_addr(mac_info); for (i = 0; i < IOT_MAC_ADDR_LEN; i++) { if (mac_info[i] != 0) { break; } } if (i >= IOT_MAC_ADDR_LEN) { ret_st |= 1 << 1; } ate_ver = efuse_get_analog_bin_ver(); /* check ate */ ate_info = ate_ver; ate_info |= efuse_get_ft_pass_flag(); ate_info |= efuse_get_dcdc_trim(); ate_info |= efuse_get_flash_ldo_out_trim(); ate_info |= efuse_get_d_mdll_ldo_vref_trim(); ate_info |= efuse_get_d_bg_vbg_cntl(); ate_info |= efuse_get_d_bg_iccal(); ate_info |= efuse_get_rx_adc_vcm_ctrl(); ate_info |= efuse_get_flash_ldo_out_trim_2v5(); if (ate_info == 0) { ret_st |= 1 << 2; } /* check sadc meter */ ate_info = efuse_get_sadc_meter_dc_offset_code(); ate_info |= efuse_get_sadc_meter_vref_code(); ate_info |= efuse_get_sadc_meter_vcm_code(); if (ate_ver >= EFUSE_ATE_BIN_VERSION_V2) { ate_info |= efuse_get_sadc_meter_dc_offset_code_n12db(); ate_info |= efuse_get_sadc_meter_dc_offset_code_n6db(); ate_info |= efuse_get_sadc_meter_dc_offset_code_12db(); ate_info |= efuse_get_sadc_meter_dc_offset_code_24db(); } if (ate_info == 0) { ret_st |= 1 << 3; } /* check sadc tpid */ if (ate_ver >= EFUSE_ATE_BIN_VERSION_V2) { ate_info = efuse_get_sadc_tpid_dc_offset_code(); ate_info |= efuse_get_sadc_tpid_vref_code(); ate_info |= efuse_get_sadc_tpid_vcm_code(); ate_info |= efuse_get_sadc_tpid_dc_offset_code_n12db(); ate_info |= efuse_get_sadc_tpid_dc_offset_code_n6db(); ate_info |= efuse_get_sadc_tpid_dc_offset_code_12db(); ate_info |= efuse_get_sadc_tpid_dc_offset_code_24db(); if (ate_info == 0) { ret_st |= (1 << 4); } } #endif return ret_st; } bool_t efuse_prog_done_check() { if (efuse_get_idle_statue()) { return true; } return false; } void efuse_write_prog_done() { efuse_wait_ilde_vaild(); } uint32_t efuse_protect() { /* not support */ return 0; } uint32_t efuse_protect_off() { /* not support */ return 0; } uint32_t efuse_get_wafer_version() { /* not support */ return 0; } uint32_t efuse_get_reserve_version() { /* not support */ return 0; } uint32_t efuse_get_package_version() { /* not support */ return 0; } uint8_t efuse_get_pmu_ldo_trim() { /* not support */ return 0; }