953 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			953 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /****************************************************************************
 | |
| 
 | |
| 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);
 | |
| }
 | |
| 
 |