/**************************************************************************** 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 "hw_reg_api.h" #include "plc_fr.h" #include "phy_cal.h" #include "phy_bb.h" #include "phy_phase.h" #include "granite_reg.h" #include "phy_rxtd_reg.h" #include "phy_txrx_pwr.h" #include "phy_rx_fd_reg.h" #include "phy_dfe_reg.h" #include "mac_sys_reg.h" #include "iot_io.h" #include "hw_tonemask.h" #include "iot_config.h" #include "iot_pib.h" #include "iot_errno.h" #include "rx_pb_reorder.h" #include "ahb.h" #include "iot_cal_data.h" #include "phy_ana.h" #include "ahb.h" #include "hw_phy_api.h" #include "phy_ana_reg.h" #include "iot_system.h" int16_t int16_abs(int16_t x) { if(x<0) x=0-x; return x; } /* Note: wmask is useful for rx0 and top reg only */ #if PHY_CAL_PIB_SUPPORT == 1 uint32_t tx_dc_calibration(int16_t *tx_dc, iot_pib_w_halphy_real_cfg_t *pib_ptr) #else uint32_t tx_dc_calibration(uint16_t *tx_dc) #endif { uint32_t rodata = 0; volatile uint16_t dac_golden = 512; volatile uint16_t dac_ovr = 0; volatile uint16_t dac_step = 0; int16_t dc_offset = 0; /* force phy in idle state */ phy_txrx_ovr_set(true,0); /* auto gain */ phy_agc_gain_lvl_set(0,60,-24,0); /* sw control tx rx */ phy_ana_hw_en_bitmap(0); /* en analog tx */ phy_ana_tx_set(true, true); phy_ana_rx_set(false, false); /* en tx compen */ phy_ana_tx_comp_set(1); /* reset the dc correction register */ phy_dfe_dc_comp_set(0,0); phy_dfe_dc_comp_set(1,0); phy_dfe_dc_comp_set(2,0); phy_dfe_dc_comp_set(3,0); phy_dfe_dc_comp_set(4,0); phy_dfe_dc_comp_set(5,0); phy_dfe_dc_comp_set(6,0); phy_dfe_dc_comp_set(7,0); /* dc offset */ for(uint32_t i = 0; i < PHY_TX_DC_CAL_LENGTH; i++) { phy_ana_tx_gpga_set(i); /* if(phy_dfe_dc_comp_get(i)>>9) { dac_golden = PHY_DAC_STEP + phy_dfe_dc_comp_get(i) - 1024; } else{ dac_golden = PHY_DAC_STEP + phy_dfe_dc_comp_get(i); } */ dac_golden = 512; dac_step = dac_golden; dac_ovr = dac_step; do{ phy_dac_data_ovr_set(true,dac_ovr); //phy_ana_i2c_read(reg_id, &rdata, &rodata); rodata = phy_ana_tx_pgacomp_read(); dac_step = dac_step >> 1; if(rodata == 1){//power compare. dac_ovr += dac_step; } else{ dac_ovr -= dac_step; } }while(dac_step > 0); dc_offset = dac_ovr-512; if(tx_dc != NULL) { *tx_dc = dc_offset; tx_dc++; #if PHY_CAL_PIB_SUPPORT == 1 /*todo: update pib */ pib_ptr->tx_dc[i] = dc_offset; #endif } else{ IOT_ASSERT(0); } if(int16_abs(dc_offset)>TX_DC_THR){ iot_printf("tx dc calibration: i=%d, dac_cal=%d, ###fail###\r\n", \ i, dc_offset); /* set tx dc compen */ phy_dfe_dc_comp_set(i, 0); } else{ iot_printf("tx dc calibration: i=%d, dac_cal=%d, ###success###\r\n", \ i, dc_offset); /* set tx dc compen */ phy_dfe_dc_comp_set(i, dc_offset); } } /* disable tx compen */ phy_ana_tx_comp_set(0); /* disable analog tx */ phy_ana_tx_set(false, false); /* clear ovr */ phy_dac_data_ovr_set(0,0); /* hw control tx rx */ phy_ana_hw_en_bitmap(~0); return ERR_OK; } /* Note: wmask is useful for rx0 and top reg only */ #if PHY_CAL_PIB_SUPPORT == 1 uint32_t rx_dc_calibration(uint32_t *rx_dc, \ iot_pib_w_halphy_real_cfg_t *pib_ptr) #else uint32_t rx_dc_calibration(uint16_t *rx_dc) #endif { uint32_t ret = ERR_OK; uint32_t tmp = 0; volatile uint8_t flag = 0; uint16_t i = 0 ,j = 0; int16_t dc_offset = 0; int16_t dc_offset_after_pgf = 0; int8_t gain = 0; volatile uint16_t dc_val = 0; volatile uint16_t dc_pgf = 0; volatile uint16_t dc_pga = 0; volatile uint16_t dc_step = 0; uint8_t pgf = 0, bq = 0, pga = 0, bq_qvalue =0; uint8_t lna = 0, byphpf = 0, enord2 = 0; uint32_t start_time = 0, end_time = 0; uint64_t time_span = 0; phy_add_dc_cal_cnt(); /* disable packet detect timeout */ phy_pkt_time_out_disable(true); /* disable reset by full */ phy_agc_sat_adj_set(1, 1); /* force phy in rx state */ phy_txrx_ovr_set(true,1); /* sw control tx rx */ phy_ana_hw_en_bitmap(0); /* diable analog loopen */ phy_ana_rx_pgfloop_set(0); if(!iot_chip_check_lic()) { phy_phase_ovr_set(PHY_PHASE_OVR_ALL,true,PHY_TXRX_OVR_IDLE); } /* force adc/rx enable and disable geode */ phy_ana_rx_fe_set(1); phy_ana_adc_set(1); phy_ana_top_enlic_rx_set(0); phy_ana_top_enlic_tx_set(0); phy_ana_top_dac_en(0); phy_ana_top_tx_en(0); phy_ana_top_reset_n_set(1); /* check raw_dc start*/ /* granite gain=0, pwdpgfoffset=1, pwdpgaoffset=1, hpfenord2=1 */ phy_ana_rx_fe_gpgf(3); phy_ana_rx_fe_gbq(1); phy_ana_rx_fe_gpga(0); phy_ana_rx_fe_gpga_offset(PHY_RX_PGA_OFFSET_DFT); phy_ana_rx_fe_gpgf_offset(PHY_RX_PGF_OFFSET_DFT); phy_ana_rx_fe_hpfenord2_set(1); phy_ana_rx_fe_byphpf_set(0); phy_ana_rx_fe_pwdpgf_offset_set(1); phy_ana_rx_fe_pwdpga_offset_set(1); /* delay 3us */ start_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR); do{ end_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR); time_span = end_time - start_time; if (time_span < 0) { // wrap around time_span = (0x100000000LL) - start_time + end_time; } }while(time_span < 3*TICKS_US); /* get dc est */ dc_offset = 0; for(j = 0; j< PHY_DC_EST_RETRY_NUM; j++) { tmp = PHY_RXTD_READ_REG(CFG_BB_PACKET_INF_2_ADDR); flag = REG_FIELD_GET(DC_EST_FREE,tmp) >> 9; if(flag) { dc_offset += REG_FIELD_GET(DC_EST_FREE,tmp) - 1024; } else { dc_offset += REG_FIELD_GET(DC_EST_FREE,tmp); } } dc_offset = dc_offset/PHY_DC_EST_RETRY_NUM; #if IOT_DTEST_ONLY_SUPPORT == 1 iot_printf("raw_dc with 0db gain and pwd correction dac is %d\r\n", \ dc_offset); #endif if(int16_abs(dc_offset)>RX_DC_RAW_THR) { iot_printf("raw_dc=%d is too large! ###fail###\r\n",dc_offset); ret = ERR_FAIL; } /*write back RX0 register*/ phy_ana_rx_fe_gpgf(3); phy_ana_rx_fe_gbq(1); phy_ana_rx_fe_gpga(0); phy_ana_rx_fe_gpga_offset(PHY_RX_PGA_OFFSET_DFT); phy_ana_rx_fe_gpgf_offset(PHY_RX_PGF_OFFSET_DFT); phy_ana_rx_fe_hpfenord2_set(1); phy_ana_rx_fe_byphpf_set(0); phy_ana_rx_fe_pwdpgf_offset_set(0); phy_ana_rx_fe_pwdpga_offset_set(0); /* check raw_dc end*/ /* scan normal and narrow gain table */ for(i = 0; i < PHY_GAIN_STEP_MAX * 2; i++) { /* get current gain info */ if(i < PHY_GAIN_STEP_MAX) { gain = i - 24; } else { gain = i - PHY_GAIN_STEP_MAX - 24; } dc_pga = 0; dc_pgf = 0; /* fix gain accss from analog */ phy_pgf_bq_pga_gain_get(i, \ &pgf, \ &bq, \ &pga, \ &lna, \ &byphpf, \ &enord2, \ &bq_qvalue); phy_ana_rx_fe_gpga_offset(pga); phy_ana_rx_fe_gpgf_offset(pgf); phy_ana_rx_fe_gbq(bq); phy_ana_rx_fe_byphpf_set(byphpf); phy_ana_rx_fe_hpfenord2_set(enord2); phy_ana_rx_bq_qvalue(bq_qvalue); #if PHY_LNA_DC_CALI_EN == 1 /* enable geode */ if(byphpf) { phy_ana_rx_glna(lna); } #endif /* step1: pgf cal */ phy_pgf_pga_dc_cal_get(i, &dc_pgf, &dc_pga); #if PHY_DBG_EN == 1 iot_printf("***** gain=%d calibration start *******\r\n",gain); #endif dc_val = PHY_RX_PGF_OFFSET_DFT; dc_step = PHY_RX_PGF_OFFSET_DFT; do{ phy_ana_rx_fe_gpga_offset(PHY_RX_PGA_OFFSET_DFT); phy_ana_rx_fe_gpgf_offset(dc_val); /* delay 3us */ start_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR); do{ end_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR); time_span = end_time - start_time; if (time_span < 0) { // wrap around time_span = (0x100000000LL) - start_time + end_time; } }while(time_span < 3*TICKS_US); /* get dc est */ dc_offset = 0; for(j = 0; j< PHY_DC_EST_RETRY_NUM; j++) { tmp = PHY_RXTD_READ_REG(CFG_BB_PACKET_INF_2_ADDR); flag = REG_FIELD_GET(DC_EST_FREE,tmp) >> 9; if(flag) { dc_offset += REG_FIELD_GET(DC_EST_FREE,tmp) - 1024; } else { dc_offset += REG_FIELD_GET(DC_EST_FREE,tmp); } } dc_offset = dc_offset/PHY_DC_EST_RETRY_NUM; #if PHY_DBG_EN == 1 iot_printf("rx pgf dc cali: pgfoffset=%d,dc=%d\r\n", \ dc_val, dc_offset); #endif /* PGF thd */ if(dc_offset < PHY_DC_PGF_GOLDEN && \ dc_offset > -PHY_DC_PGF_GOLDEN) { break; } /* check dc result */ if(dc_val > 48 || dc_val < 16) { break; } /* cal step to cal dc */ dc_step = dc_step >> 1; if(dc_offset > 0) { dc_val -= dc_step; } else { dc_val += dc_step; } }while(dc_step > 0); dc_pgf = dc_val; #if PHY_DBG_EN == 1 iot_printf("rx pgf cali done: gain=%d, pgfoffset=%d\r\n", \ gain, dc_pgf); #endif dc_offset_after_pgf = dc_offset; /* step2: pga cal */ dc_val = PHY_RX_PGA_OFFSET_DFT; dc_step = PHY_RX_PGA_OFFSET_DFT; do{ phy_ana_rx_fe_gpga_offset(dc_val); phy_ana_rx_fe_gpgf_offset(dc_pgf); /* delay 3us */ start_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR); do{ end_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR); time_span = end_time - start_time; if (time_span < 0) { // wrap around time_span = (0x100000000LL) - start_time + end_time; } }while(time_span < 3*TICKS_US); /* get dc est */ dc_offset = 0; for(j = 0; j< PHY_DC_EST_RETRY_NUM; j++) { tmp = PHY_RXTD_READ_REG(CFG_BB_PACKET_INF_2_ADDR); flag = REG_FIELD_GET(DC_EST_FREE,tmp)>>9; if(flag) { dc_offset += REG_FIELD_GET(DC_EST_FREE,tmp) - 1024; } else { dc_offset += REG_FIELD_GET(DC_EST_FREE,tmp); } } dc_offset = dc_offset/PHY_DC_EST_RETRY_NUM; #if PHY_DBG_EN == 1 iot_printf("rx pga dc cali: pgaoffset=%d, dc=%d\r\n", \ dc_val,dc_offset); #endif if(dc_offset < PHY_DC_PGA_GOLDEN && \ dc_offset > -PHY_DC_PGA_GOLDEN) { break; } /* cal step to cal dc */ dc_step = dc_step >> 1; if(dc_offset > 0) { dc_val -= dc_step; } else { dc_val += dc_step; } }while(dc_step > 0); dc_pga = dc_val; if(int16_abs(dc_offset)>int16_abs(dc_offset_after_pgf)) { dc_offset = dc_offset_after_pgf; dc_pga = PHY_RX_PGA_OFFSET_DFT; } if(int16_abs(dc_offset)>RX_DC_FINAL_THR) { #if IOT_DTEST_ONLY_SUPPORT == 1 iot_printf("rx pga dc cali done: gain=%d,pgf=%d,bq=%d,pga=%d,", \ gain, pgf, bq, pga); #endif iot_printf("pgfoffset=%d,pgaoffset=%d, final_dc=%0d ###fail###\r\n", \ dc_pgf, dc_pga, dc_offset); ret = ERR_FAIL; } else { #if IOT_DTEST_ONLY_SUPPORT == 1 iot_printf("rx pga dc cali done: gain=%d,pgf=%d,bq=%d,pga=%d,", \ gain, pgf, bq, pga); #endif iot_printf("pgfoffset=%d,pgaoffset=%d, final_dc=%0d ###success###\r\n", \ dc_pgf, dc_pga, dc_offset); } /* set pgf and pga dc offset to gain table */ phy_pgf_pga_dc_cal(i, dc_pgf, dc_pga); if(rx_dc != NULL) { *rx_dc = (dc_pgf & 0x3F) | \ ((dc_pga & 0x1F) << 6); rx_dc++; #if PHY_CAL_PIB_SUPPORT == 1 //todo: support pib pib_ptr->rx_dc[i] = dc_pgf | (dc_pga << 6); #endif } else { IOT_ASSERT(0); } } /* disable force tx/rx to avoid mac hang */ phy_txrx_ovr_set(0,0); /* K68 branch*/ if(!iot_chip_check_lic()) { phy_phase_ovr_set(PHY_PHASE_OVR_ALL,false,PHY_TXRX_OVR_IDLE); } /* disable packet detect timeout */ phy_pkt_time_out_disable(false); /* disable reset by full */ phy_agc_sat_adj_set(1, 0); /* hw control tx rx */ phy_ana_hw_en_bitmap(~0); (void)gain; return ret; } void phy_txrx_loop_back_begin(uint32_t phase, TXRX_LOOP_BACK_MODE_ID mode) { uint32_t tmp = 0; /* Must not ovr da data */ phy_dac_data_ovr_set(false,0); /* force inte rx state */ phy_txrx_ovr_set(1,1); /* disable packet detect timeout */ phy_pkt_time_out_disable(true); /* bypass dc blocker */ tmp = PHY_DFE_READ_REG(CFG_BB_DC_BLK_STAGE_DLY_ADDR); REG_FIELD_SET(SW_DC_BLK_BYPASS, tmp, 1); PHY_DFE_WRITE_REG(CFG_BB_DC_BLK_STAGE_DLY_ADDR, tmp); /* fix gain and disable agc */ phy_agc_gain_lvl_set(1,0,-24,0); /* disable adj and sat reset */ phy_agc_sat_adj_set(1, 1); /* disable auto-adjust gain */ phy_agc_gain_adj_dis(0); /* enable analog tx and rx */ phy_ana_top_tx_en(1); phy_ana_top_rx_en(1); phy_ana_top_adc_en(1); phy_ana_top_dac_en(1); phy_ana_top_reset_n_set(1); #if CHIP_BRINGUP_DEBUG == 1 /* recovery default value */ PHY_ANA_WRITE_REG(CFG_BB_ANA_TX_CFG_0_ADDR, 0x0100007e); #endif /* enable rx ppm bypass when tone gen enable */ tmp = PHY_DFE_READ_REG(CFG_BB_PPM_CFG2_ADDR); REG_FIELD_SET(SW_RX_PPM_BYPASS, tmp, 1); PHY_DFE_WRITE_REG(CFG_BB_PPM_CFG2_ADDR, tmp); tmp = PHY_DFE_READ_REG(CFG_BB_LOOPBACK_TEST_CFG_ADDR); REG_FIELD_SET(SW_LOOPBACK_EN, tmp, 1); PHY_DFE_WRITE_REG(CFG_BB_LOOPBACK_TEST_CFG_ADDR, tmp); if(mode == TXRX_LOOP_BACK_GRANITE) { /* enable analog loopen */ phy_ana_rx_bq_qvalue(8); phy_ana_rx_fe_gpgf(1); phy_ana_rx_fe_gbq(1); phy_ana_rx_fe_gpga(0); phy_ana_rx_pgfloop_set(1); phy_ana_rx_fe_gpga_offset(16); phy_ana_rx_fe_gpgf_offset(32); } else if(mode == TXRX_LOOP_BACK_GEODE) { /* disable analog loopen */ phy_ana_rx_pgfloop_set(0); /* k48 or k68 */ if(iot_chip_check_lic()) { phy_ana_top_enlic_rx_set(1); phy_ana_top_enlic_tx_set(1); } else { /* enable a/b/c and tx & rx*/ switch(phase) { case 0: phy_phase_ovr_set(PHY_PHASE_OVR_A,1,3); break; case 1: phy_phase_ovr_set(PHY_PHASE_OVR_B,1,3); break; case 2: phy_phase_ovr_set(PHY_PHASE_OVR_C,1,3); break; case 3: phy_phase_ovr_set(PHY_PHASE_OVR_ALL,1,3); break; default: break; } } } /* tone */ tmp = PHY_DFE_READ_REG(CFG_BB_TX_TONE_0_CFG_ADDR); phy_dfe_tone_cfg(1,REG_FIELD_GET(SW_TONE_0_CFG_NUM,tmp), \ REG_FIELD_GET(SW_TONE_1_CFG_NUM,tmp)); /* loopback if < 6, will full */ #if IOT_DTEST_ONLY_SUPPORT == 1 phy_dfe_tone_att_cfg(0,3,3); #endif } void phy_txrx_loop_back_end() { uint32_t tmp = 0; /* fallback:disable tone */ phy_dfe_tone_cfg(0,0,0); /* en dc blocker */ tmp = PHY_DFE_READ_REG(CFG_BB_DC_BLK_STAGE_DLY_ADDR); REG_FIELD_SET(SW_DC_BLK_BYPASS, tmp, 0); PHY_DFE_WRITE_REG(CFG_BB_DC_BLK_STAGE_DLY_ADDR, tmp); phy_agc_sat_adj_set(0, 0); tmp = PHY_DFE_READ_REG(CFG_BB_LOOPBACK_TEST_CFG_ADDR); REG_FIELD_SET(SW_LOOPBACK_EN, tmp, 0); PHY_DFE_WRITE_REG(CFG_BB_LOOPBACK_TEST_CFG_ADDR, tmp); /* disable packet detect timeout */ phy_pkt_time_out_disable(false); /* config regression */ phy_ana_rx_pgfloop_set(0); /* recover rx ppm bypass */ tmp = PHY_DFE_READ_REG(CFG_BB_PPM_CFG2_ADDR); REG_FIELD_SET(SW_RX_PPM_BYPASS, tmp, 0); PHY_DFE_WRITE_REG(CFG_BB_PPM_CFG2_ADDR, tmp); } uint32_t phy_csi_buf_amp_get(uint16_t tone_id) { uint32_t tmp = 0; uint32_t fft_loop = 1; uint32_t amp_val = 0; int16_t csi_i = 0, csi_q = 0; uint32_t *csi_buf = (uint32_t *)BB_CSI_BASEADDR; /* reset phy */ phy_reset(PHY_RST_REASON_WARM); /* config det tone */ phy_rxfd_rate0_det(0, TOTAL_TONE_MASK_NUM - 4); /* enable ana loopback */ phy_txrx_loop_back_begin(0,TXRX_LOOP_BACK_GRANITE); /* trig fft */ tmp = PHY_DFE_READ_REG(CFG_BB_LOOPBACK_TEST_CFG_ADDR); REG_FIELD_SET(SW_LOOP_FFT_CYCLE, tmp, fft_loop); REG_FIELD_SET(SW_LOOP_FFT_START, tmp, 1); PHY_DFE_WRITE_REG(CFG_BB_LOOPBACK_TEST_CFG_ADDR, tmp); /* wait fft done */ do{ tmp = PHY_DFE_READ_REG(CFG_BB_LOOPBACK_TEST_CFG_ADDR); }while(!REG_FIELD_GET(LOOP_FFT_DONE, tmp)); /* enable sw csi buf access */ enable_sw_access_csi_buf(1); /* cal csi for appointed tone */ csi_i = (int16_t)(*(csi_buf + tone_id) & 0xFFFF); csi_q = (int16_t)(*(csi_buf + tone_id) >> 16); amp_val = csi_i*csi_i + csi_q*csi_q; /* enable sw csi buf access */ enable_sw_access_csi_buf(0); /* recover to the state set in ana loopback */ phy_txrx_loop_back_end(); /* config det tone */ phy_update_tone_det_range(); return amp_val; } /* * rx bandwidth filter: * rx_freq LPF(typ) Min Max * 5.6M 63/5.790M 59 63 * 12M 23/12.129M 18 30 * fix big attenuation: * 8M 36 29 45 * 15M 19 14 24 * 20M 14 11 18 * X/Y = 10^(3/10) = 1.995 */ uint16_t phy_rx_bw_filter(RX_BW_LIST_ID freq_id) { uint32_t amp_val = 0; uint16_t tone_id = 0; uint16_t cap_id = 0; uint16_t start_cap = 0, end_cap = 0; uint32_t golden_data = 0; uint8_t is_thd_find = false; /* sw control tx rx */ phy_ana_hw_en_bitmap(0); tone_id = 41; /* 1st get 3M amp */ phy_dfe_tone_cfg(1,tone_id,0); phy_dfe_tone_att_cfg(0,3,3); phy_ana_rx_fe_selc_pgf_bq(6); golden_data = phy_csi_buf_amp_get(tone_id*3); /* tx tone is trible than cfg */ switch(freq_id) { case RX_BW_LIST_BAND0_20M: start_cap = 15; end_cap = 31; tone_id = PHY_SG_BAND0_TONE_20M/3; break; case RX_BW_LIST_BAND0_15M: start_cap = 21; end_cap = 43; tone_id = PHY_SG_BAND0_TONE_15M/3; break; case RX_BW_LIST_BAND0_12M: start_cap = 27; end_cap = 52; tone_id = PHY_SG_BAND0_TONE_12M/3; break; case RX_BW_LIST_BAND0_8M: start_cap = 40; end_cap = 79; tone_id = PHY_SG_BAND0_TONE_8M/3; break; case RX_BW_LIST_BAND1_5P6M: start_cap = 60; end_cap = 114; tone_id = PHY_SG_BAND1_TONE_5P6M/3; break; default: break; } /* find the 3dB point */ for(cap_id = start_cap; cap_id <= end_cap; cap_id++) { /* update rx_selc*/ phy_ana_rx_fe_selc_pgf_bq(cap_id); /* get the amp from the fixed tone */ phy_dfe_tone_cfg(1,tone_id,0); phy_dfe_tone_att_cfg(0,3,3); amp_val = phy_csi_buf_amp_get(tone_id*3); #if CHIP_BRINGUP_DEBUG == 1 iot_printf("tone_id=%d,csi_buf_amp_val=%d\n", tone_id*3, amp_val); #endif if(golden_data > (amp_val << 1)){ is_thd_find = true; break; } } /* hw control tx rx */ phy_ana_hw_en_bitmap(~0); if(is_thd_find){ /* update the cap value*/ iot_printf("bw filter cal:band=%d,cap value=%d\r\n",freq_id,cap_id); } else if(end_cap == 127){ iot_printf("bw filter cal:band=%d,cap value bigger than 63\r\n",freq_id); return 127; } else{ iot_printf("bw filter cal:band=%d fail \r\n",freq_id); return 0; } return cap_id; } /* read ppm, dc cali and update to hw */ void phy_load_cal_cfg(void) { uint16_t tx_dc[PHY_TX_DC_CAL_LENGTH] = {0}; uint16_t *rx_dc = NULL; /* alloc rx dc mem */ rx_dc = (uint16_t *)os_mem_malloc( \ PLC_PHY_COMMON_MID, \ PHY_GAIN_STEP_MAX << 2); if(rx_dc == NULL) { iot_printf("%s: malloc rx dc fail!\n", __FUNCTION__); IOT_ASSERT(0); } #if IOT_DTEST_ONLY_SUPPORT == 0 uint32_t i = 0; uint32_t ret = ERR_FAIL; uint8_t *section; uint8_t pib_type = 0; uint16_t dc_pgf = 0; uint16_t dc_pga = 0; iot_pib_w_halphy_real_cfg_t *phy_cfg; #if PLC_SUPPORT_CCO_ROLE == 0 iot_cal_data_cfg_t *cal_cfg; /* init perf ppm */ g_phy_ctxt.dep.phy_ppm_pref = PHY_PPM_PREF_DFT; g_phy_ctxt.dep.phy_ppm_init = PHY_PPM_PREF_DFT; /* read crystal ppm from oem */ ret = iot_cal_data_get_cfg(&cal_cfg); if (ret == ERR_OK || ret == ERR_NOSUPP) { iot_printf("[PHY %d]oem load successfully!\n", ret); /* check mtd sts */ if (iot_cal_data_get_mtd_sts() != ERR_OK) { iot_printf("[PHY]oem mtd status check fail!\n"); } else { /* check mask if valid */ if (iot_cal_data_check_mask(cal_cfg, IOT_PHY_CFG_MASK_PPM)) { /* disable td and fd comp self */ phy_freq_shift_self_comp(false, false); /* g_phy_ctxt.phy_ppm_pref = target crystal ppm * cal_cfg->halphy_cfg.ppm = - local crystal ppm * ppm of phy_ppm_cal_set(to self): * + : faster - : more slowly */ /* apply ppm to phy register */ g_phy_ctxt.dep.phy_ppm_init = g_phy_ctxt.dep.phy_ppm_pref + cal_cfg->halphy_cfg.ppm; uint32_t ver = cal_cfg->halphy_cfg.pt_fw_ver; iot_printf("phy oem ver:0x%x\n", ver); if (ver && 0xFFFFFFFF != ver) { g_phy_ctxt.dep.phy_cal_ppm_in_oem = g_phy_ctxt.dep.phy_ppm_init; } else { g_phy_ctxt.dep.phy_cal_ppm_in_oem = FORCE_INI_PPM; } g_phy_ctxt.dep.phy_ppm_init = phy_ppm_cal_hw_val(PHY_CAL_UNIT_1_1, g_phy_ctxt.dep.phy_cal_ppm_in_oem, IOT_SUPPORT_RATE_SR); //TODO: maybe phy_ppm_init save to g_phy_cpu_share_ctxt only g_phy_cpu_share_ctxt.phy_ppm_init = g_phy_ctxt.dep.phy_ppm_init; #if PLC_SUPPORT_CCO_ROLE == 0 /* only sta apply this info * cco just read and save in * phy_cal_ppm_in_oem */ phy_ppm_set(g_phy_ctxt.dep.phy_ppm_init, BB_PPM_TXRX); #endif iot_printf("[PHY]config ppm:%d " "(pref ppm:%d, oem ppm:%d ) to phy_reg.\n", g_phy_ctxt.dep.phy_ppm_init, g_phy_ctxt.dep.phy_ppm_pref, cal_cfg->halphy_cfg.ppm); } else { iot_printf("[PHY]oem magic num check fail!\n"); } } } else { iot_printf("[PHY]oem load failed, err code: %d.\n", ret); } #endif /* get dc cal from pib */ ret = iot_pib_get_section(IOT_PIB_HALPHY_ID, §ion, &pib_type, IOT_PIB_APP_GET_WRITE_SECTION); if (ret == ERR_OK) { phy_cfg = (iot_pib_w_halphy_real_cfg_t *)section; /* check tx dc if valid */ if (phy_cfg->mask & (1 << IOT_PIB_PHY_MASK_TX_DC)) { /* apply dc calibration */ for(i = 0; i < TOTAL_TX_DC_NUM; i++) { phy_dfe_dc_comp_set(i, phy_cfg->tx_dc[i]); } } else { iot_printf("%s pib have no valid tx dc data.\n", __FUNCTION__); #if PHY_CAL_PIB_SUPPORT == 1 /* commit pib write if need in the future */ tx_dc_calibration(tx_dc, phy_cfg); #else tx_dc_calibration(tx_dc); #endif } /* check rx dc if valid */ if (phy_cfg->mask & (1 << IOT_PIB_PHY_MASK_RX_DC)) { for(i = 0; i < TOTAL_GAIN_NUM; i++) { dc_pgf = phy_cfg->rx_dc[i] & 0x3F; dc_pga = (phy_cfg->rx_dc[i] & 0xFC0) >> 6; phy_pgf_pga_dc_cal(i, dc_pgf, dc_pga); } } else { iot_printf("%s pib have no valid rx dc data.\n", __FUNCTION__); #if PHY_CAL_PIB_SUPPORT == 1 /* commit pib write if need in the future */ rx_dc_calibration(rx_dc, phy_cfg); #else rx_dc_calibration(rx_dc); #endif } /* check bandwidth filter calibration */ if (phy_cfg->mask & (1 << IOT_PIB_PHY_MASK_BW_FILTER)) { /* update global variables for freshing */ g_phy_ctxt.dep.band_15m_cap_set = \ phy_cfg->cap_set[RX_BW_LIST_BAND0_15M]; g_phy_ctxt.dep.band_8m_cap_set = \ phy_cfg->cap_set[RX_BW_LIST_BAND0_8M]; g_phy_ctxt.dep.band_20m_cap_set = \ phy_cfg->cap_set[RX_BW_LIST_BAND0_20M]; } else { iot_printf("%s pib have no valid bw filter data.\n", __FUNCTION__); /* cali 15M/band0 and 8M/band1 */ phy_param_init(PHY_PROTO_TYPE_GET()); g_phy_ctxt.dep.band_20m_cap_set = \ phy_rx_bw_filter(RX_BW_LIST_BAND0_20M); g_phy_ctxt.dep.band_15m_cap_set = \ phy_rx_bw_filter(RX_BW_LIST_BAND0_15M); g_phy_ctxt.dep.band_8m_cap_set = \ phy_rx_bw_filter(RX_BW_LIST_BAND0_8M); } } else { iot_printf("%s cal load fail, calibrate again!\n", __FUNCTION__); tx_dc_calibration(tx_dc); rx_dc_calibration(rx_dc); /* cali 15M/band0 and 8M/band1 */ phy_param_init(PHY_PROTO_TYPE_GET()); g_phy_ctxt.dep.band_20m_cap_set = \ phy_rx_bw_filter(RX_BW_LIST_BAND0_20M); g_phy_ctxt.dep.band_15m_cap_set = \ phy_rx_bw_filter(RX_BW_LIST_BAND0_15M); g_phy_ctxt.dep.band_8m_cap_set = \ phy_rx_bw_filter(RX_BW_LIST_BAND0_8M); } /* commit pib write if need in the future */ #if PHY_CAL_PIB_SUPPORT == 1 uint8_t ref = 0; uint16_t ticket = 0; iot_pib_acquire_commit_ref(IOT_PIB_HALPHY_ID, &ref); iot_pib_release_commit_ref(IOT_PIB_HALPHY_ID, &ref); iot_pib_commit(IOT_PIB_HALPHY_ID, COMMIT_TYPE_WAIT_REFZERO, &ticket); #endif #else tx_dc_calibration(tx_dc); rx_dc_calibration(rx_dc); /* cali 15M/band0 and 8M/band1 */ phy_param_init(PHY_PROTO_TYPE_GET()); g_phy_ctxt.dep.band_20m_cap_set = \ phy_rx_bw_filter(RX_BW_LIST_BAND0_20M); g_phy_ctxt.dep.band_15m_cap_set = \ phy_rx_bw_filter(RX_BW_LIST_BAND0_15M); g_phy_ctxt.dep.band_8m_cap_set = \ phy_rx_bw_filter(RX_BW_LIST_BAND0_8M); #endif /* release malloc */ os_mem_free(rx_dc); /* ana reset */ ahb_phy_ana_reset(); /* load new dc cali table */ phy_gain_tab_load(all_mask_gain_table); }