668 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			668 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /****************************************************************************
 | ||
|  *
 | ||
|  * 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 "ate_main.h"
 | ||
| #include "iot_bitops.h"
 | ||
| #include "dbg_io.h"
 | ||
| #include "iot_io.h"
 | ||
| #include "iot_clock.h"
 | ||
| #include "gp_timer.h"
 | ||
| #include "phy_cal.h"
 | ||
| #include "mac_rx_test.h"
 | ||
| #include <string.h>
 | ||
| #include "phy_bb.h"
 | ||
| #include "plc_protocol.h"
 | ||
| #include "plc_mpdu_header.h"
 | ||
| #include "granite_reg.h"
 | ||
| #include "phy_dfe_reg.h"
 | ||
| #include "phy_ana_glb.h"
 | ||
| #include "phy_ana.h"
 | ||
| #include "clk.h"
 | ||
| #include "math_log10.h"
 | ||
| #include "efuse.h"
 | ||
| #include "efuse_mapping.h"
 | ||
| #include "hw_phy_init.h"
 | ||
| #include "mac_reset.h"
 | ||
| //#include "sadc_t.h"
 | ||
| #include "ahb_rf.h"
 | ||
| #include "apb_glb_reg.h"
 | ||
| #include "mac_sys_reg.h"
 | ||
| #include "os_mem.h"
 | ||
| #include "iot_errno.h"
 | ||
| #include "wdg_reg.h"
 | ||
| #include "watchdog.h"
 | ||
| #include "phy_rxtd_reg.h"
 | ||
| #include "phy_phase.h"
 | ||
| #include "phy_tools.h"
 | ||
| #include "hal_rx.h"
 | ||
| 
 | ||
| #include "sfc_rf.h"
 | ||
| #include "sfc.h"
 | ||
| #include "flash.h"
 | ||
| #include "gpio_mtx.h"
 | ||
| #include "apb.h"
 | ||
| #include "iot_gpio_api.h"
 | ||
| #include "sadc_hw.h"
 | ||
| #include "sadc_t.h"
 | ||
| #include "hal_sadc.h"
 | ||
| #include "ana_pmu_wrap_rf.h"
 | ||
| #include "hw_sadc.h"
 | ||
| #include "iot_wdg_api.h"
 | ||
| 
 | ||
| /* ate global structure */
 | ||
| ate_info_t *glb_ate_info = (ate_info_t *) 0xfff8000;//0x73FC2000
 | ||
| 
 | ||
| /********************************************************************************
 | ||
| Test item
 | ||
|     TX gain setting
 | ||
|     sw_tone_0_att   sw_tx_pwr_scale     TX_PGA_gain
 | ||
|     RX gain setting
 | ||
|     RX_PGF_gain RX_BQ_gain RX_PGA_gain sw_rx_gain_shift CSI_power(I^2+Q^2)(dBLSB)
 | ||
| TX gain
 | ||
|     -24  0   -4.53   -6    0   0   0   70.269
 | ||
|     -24  0   1.47    -6    0   0   1   70.269
 | ||
|     -24  0   7.47    -6    0   0   2   70.269
 | ||
|     -24  0   13.47   -6    0   0   3   70.269
 | ||
| RX gain
 | ||
|     -24  0   1.47    -6    0   0   1   70.269
 | ||
|     -24  0   1.47    -6   -6  12   2   70.269
 | ||
|     -24  0   1.47    -6   12   0   3   70.269
 | ||
|     -24  0   1.47    -6    0   6   2   70.269
 | ||
| TX PGA
 | ||
|     0~3  -4.5, 1.5, 7.5, 13.5
 | ||
| ********************************************************************************/
 | ||
| ate_loop_back_gain_list_t ate_granite_lpbk_gain_list[] =
 | ||
| {
 | ||
|     {1,  0,  0,  0,  1,  0,  1,  0},
 | ||
|     {2,  0,  1,  0,  1,  0,  1,  0},
 | ||
|     {3,  0,  2,  0,  1,  0,  0,  0},
 | ||
|     {4,  0,  3,  0,  1,  0,  0,  0},
 | ||
|     {1,  0,  0,  0,  1,  0,  0,  0},
 | ||
|     {2,  0,  0,  0,  0,  8,  0,  0},
 | ||
|     {3,  0,  1,  0,  1,  4,  0,  0},
 | ||
|     {4,  0,  1,  0,  3,  0,  0,  0},
 | ||
| };
 | ||
| /*tx_tone_att, tx_factor, tx_pga_gain, rx_pgf_gain, rx_bq_gain, rx_pga_gain, rx_shift, rx_lna_gain*/
 | ||
| ate_loop_back_gain_list_t ate_geode_lpbk_gain_list[] =
 | ||
| {
 | ||
|     {1, 0,  1,  3,  0,  0,  0, 1},
 | ||
|     {1, 0,  1,  2,  0,  0,  0, 2},
 | ||
|     {1, 0,  1,  1,  0,  0,  0, 3},
 | ||
|     {1, 0,  1,  0,  0,  0,  0, 4},
 | ||
|     {1, 0,  0,  0,  0,  0,  0, 5},
 | ||
|     {2, 0,  0,  0,  0,  0,  0, 6},
 | ||
|     {3, 0,  0,  0,  0,  0,  0, 7},
 | ||
| };
 | ||
| 
 | ||
| /* initialize ate */
 | ||
| void ate_init(void)
 | ||
| {
 | ||
|     uint32_t tmp = 0;
 | ||
| 
 | ||
|     /* init global info */
 | ||
|     memset(glb_ate_info, 0, sizeof(ate_info_t));
 | ||
| 
 | ||
|     /* change clk to 150M */
 | ||
|     clk_core_freq_set(CPU_FREQ_150M);
 | ||
| 
 | ||
|     gp_timer_init();
 | ||
|     gp_timer_enable(0,0,0);
 | ||
| 
 | ||
|     /* alloc 1K size ram */
 | ||
|     os_mem_init((uint8_t *)0xffffc00, 0x1000);
 | ||
| 
 | ||
|     /* eb clk */
 | ||
|     tmp = 0xFFFFFFFF;
 | ||
|     AHB_RF_WRITE_REG(CFG_AHB_REG1_ADDR, tmp);
 | ||
|     /* sadc eb */
 | ||
|     tmp = APB_GLB_READ_REG(CFG_APB_GLB_GEN0_ADDR);
 | ||
|     REG_FIELD_SET(SADC_EB, tmp, 1);
 | ||
|     APB_GLB_WRITE_REG(CFG_APB_GLB_GEN0_ADDR, tmp);
 | ||
| 
 | ||
|     /* basic data struct init for bit ops */
 | ||
|     iot_bitops_init();
 | ||
| 
 | ||
|     /* reset mac */
 | ||
|     mac_reset(MAC_RST_REASON_COLD);
 | ||
|     /* reset phy */
 | ||
|     phy_reset(PHY_RST_REASON_COLD);
 | ||
|     /* reset mac */
 | ||
|     mac_reset(MAC_RST_REASON_COLD);
 | ||
| 
 | ||
|     /* phy param init */
 | ||
|     phy_param_init(PHY_PROTO_TYPE_GET());
 | ||
| 
 | ||
|     iot_wdg_enable();
 | ||
| 
 | ||
|     /* print software version */
 | ||
|     iot_printf("[ATE]software version:%s\r\n", ATE_SW_VER);
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| uint32_t mac_granite_loop_back()
 | ||
| {
 | ||
|     uint32_t ret = ERR_OK;
 | ||
|     uint32_t tmp = 0;
 | ||
|     uint32_t tone_idx = 0;
 | ||
|     uint32_t fft_loop = 1;
 | ||
|     int16_t csi_i = 0, csi_q = 0;
 | ||
|     uint32_t golden_data = 0, noise_data = 0;
 | ||
|     uint32_t *csi_buf = (uint32_t *)BB_CSI_BASEADDR;
 | ||
| 
 | ||
|     /* reset phy */
 | ||
|     phy_reset(PHY_RST_REASON_WARM);
 | ||
| 
 | ||
|     /* Must cfg start adn end tone */
 | ||
|     mac_rx_init(IOT_PLC_PHY_BAND_DFT);
 | ||
| 
 | ||
|     /* config det tone */
 | ||
|     phy_rxfd_rate0_det(0, TOTAL_TONE_MASK_NUM - 4);
 | ||
|     phy_rxfd_rate1_det(0, TOTAL_TONE_MASK_NUM - 4);
 | ||
| 
 | ||
| #if IOT_DTEST_ONLY_SUPPORT == 1
 | ||
|     /* tone 3M  */
 | ||
|     phy_dfe_tone_cfg(1, 41, 0);
 | ||
|     /* att */
 | ||
|     phy_dfe_tone_att_cfg(0, 3, 3);
 | ||
| #endif
 | ||
|     /* sw control tx rx */
 | ||
|     phy_ana_hw_en_bitmap(0);
 | ||
| 
 | ||
|     /* enable ana loopback */
 | ||
|     phy_txrx_loop_back_begin(0, TXRX_LOOP_BACK_GRANITE);
 | ||
| 
 | ||
|     for(uint32_t i = 0; \
 | ||
|         i < sizeof(ate_granite_lpbk_gain_list)/sizeof(ate_loop_back_gain_list_t); i++)
 | ||
|     {
 | ||
|         /* tone atten and tx factor */
 | ||
|         phy_dfe_tone_att_cfg(0, ate_granite_lpbk_gain_list[i].tx_tone_att, 0);
 | ||
|         //*(uint32_t *)0x51c00404 = ate_granite_lpbk_gain_list[i].tx_tone_att;
 | ||
|         phy_tx_gain_factor_set(ate_granite_lpbk_gain_list[i].tx_factor);
 | ||
| 
 | ||
|         /* tx pga */
 | ||
|         phy_ana_rx_fe_gpga(ate_granite_lpbk_gain_list[i].tx_pga_gain);
 | ||
| 
 | ||
|         /* rx pgf bq pga*/
 | ||
|         phy_ana_rx_fe_gpgf(ate_granite_lpbk_gain_list[i].rx_pgf_gain);
 | ||
|         phy_ana_rx_fe_gbq(ate_granite_lpbk_gain_list[i].rx_bq_gain);
 | ||
|         phy_ana_rx_fe_gpga(ate_granite_lpbk_gain_list[i].rx_pga_gain);
 | ||
|         /* rx scale */
 | ||
|         if (ate_granite_lpbk_gain_list[i].rx_gain_shift > 0) {
 | ||
|             phy_gain_shift_set(0, 0, 0, ate_granite_lpbk_gain_list[i].rx_gain_shift);
 | ||
|         } else {
 | ||
|             ate_granite_lpbk_gain_list[i].rx_gain_shift = -ate_granite_lpbk_gain_list[i].rx_gain_shift;
 | ||
|             phy_gain_shift_set(0, 0, 1, ate_granite_lpbk_gain_list[i].rx_gain_shift);
 | ||
|         }
 | ||
| 
 | ||
|         /* 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);
 | ||
| 
 | ||
|         /* get tone power */
 | ||
|         tone_idx = ATE_TONE_3M;
 | ||
|         csi_i = (int16_t)(*(csi_buf + tone_idx * 3) & 0xFFFF);
 | ||
|         csi_q = (int16_t)(*(csi_buf + tone_idx * 3) >> 16);
 | ||
|         golden_data = csi_i * csi_i + csi_q * csi_q;
 | ||
|         noise_data = 0;
 | ||
| 
 | ||
|         /* cal csi for every tone */
 | ||
|         for(tone_idx = 6; tone_idx < TONE_MAX_NUM; tone_idx++)
 | ||
|         {
 | ||
|             if (tone_idx != ATE_TONE_3M * 3) {
 | ||
|                 csi_i = (int16_t)(*(csi_buf + tone_idx) & 0xFFFF);
 | ||
|                 csi_q = (int16_t)(*(csi_buf + tone_idx) >> 16);
 | ||
|                 noise_data += csi_i * csi_i + csi_q * csi_q;
 | ||
|             } else {
 | ||
|                 csi_i = (int16_t)(*(csi_buf + tone_idx) & 0xFFFF);
 | ||
|                 csi_q = (int16_t)(*(csi_buf + tone_idx) >> 16);
 | ||
|             }
 | ||
| #if ATE_DEBUG_LEVEL > 1
 | ||
|             iot_printf("%d,%d,%d\r\n", tone_idx, csi_i, csi_q);
 | ||
| #endif
 | ||
|         }
 | ||
|         /* enable sw csi buf access */
 | ||
|         enable_sw_access_csi_buf(0);
 | ||
| 
 | ||
|         /* get AMP(-30dB) and SNR */
 | ||
|         glb_ate_info->csi_amp[i] = 10 * mlog10(golden_data/1000);
 | ||
|         glb_ate_info->csi_snr[i] = 10 * mlog10(golden_data/noise_data);
 | ||
|         if (glb_ate_info->csi_snr[i] >= 15) {
 | ||
|             iot_printf("[ATE]Granite AMP %d, snr %d, ###success###\r\n", \
 | ||
|                 glb_ate_info->csi_amp[i], glb_ate_info->csi_snr[i]);
 | ||
|         } else {
 | ||
|             iot_printf("[ATE]Granite AMP %d, snr %d, ###fail###\r\n", \
 | ||
|                 glb_ate_info->csi_amp[i], glb_ate_info->csi_snr[i]);
 | ||
|             ret = ERR_FAIL;
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     /* recover to the state set in ana loopback */
 | ||
|     phy_txrx_loop_back_end();
 | ||
| 
 | ||
|     /* hw control tx rx */
 | ||
|     phy_ana_hw_en_bitmap(~0);
 | ||
| 
 | ||
|     return ret;
 | ||
| }
 | ||
| 
 | ||
| uint32_t mac_geode_loop_back()
 | ||
| {
 | ||
|     uint32_t ret = ERR_OK;
 | ||
|     uint32_t tmp = 0;
 | ||
|     uint32_t tone_idx = 0;
 | ||
|     uint32_t fft_loop = 1;
 | ||
|     int16_t csi_i = 0, csi_q = 0;
 | ||
|     uint32_t golden_data = 0, noise_data = 0;
 | ||
|     uint32_t *csi_buf = (uint32_t *)BB_CSI_BASEADDR;
 | ||
| 
 | ||
|     /* reset phy */
 | ||
|     phy_reset(PHY_RST_REASON_WARM);
 | ||
| 
 | ||
|     /* cfg det tone range */
 | ||
|     phy_rxfd_rate0_det(0, TOTAL_TONE_MASK_NUM - 4);
 | ||
|     phy_rxfd_rate1_det(0, TOTAL_TONE_MASK_NUM - 4);
 | ||
| 
 | ||
|     /* tone 3M */
 | ||
|     phy_dfe_tone_cfg(1, ATE_TONE_3M, 0);
 | ||
|     /* sw control tx rx */
 | ||
|     phy_ana_hw_en_bitmap(0);
 | ||
| 
 | ||
|     /* ovr phase A/B/C */
 | ||
|     tmp = PHY_DFE_READ_REG(CFG_BB_DFE_OPTION_0_ADDR);
 | ||
|     REG_FIELD_SET(SW_ENLIC_A_OVR_EN, tmp, 1);
 | ||
|     REG_FIELD_SET(SW_ENLIC_A_OVR, tmp, 3);
 | ||
|     REG_FIELD_SET(SW_ENLIC_B_OVR_EN, tmp, 1);
 | ||
|     REG_FIELD_SET(SW_ENLIC_B_OVR, tmp, 3);
 | ||
|     REG_FIELD_SET(SW_ENLIC_C_OVR_EN, tmp, 1);
 | ||
|     REG_FIELD_SET(SW_ENLIC_C_OVR, tmp, 3);
 | ||
|     PHY_DFE_WRITE_REG(CFG_BB_DFE_OPTION_0_ADDR, tmp);
 | ||
| 
 | ||
|     /* enable ana lic tx rx */
 | ||
|     phy_ana_top_enlic_rx_set(1);
 | ||
|     phy_ana_top_enlic_tx_set(1);
 | ||
| 
 | ||
|     /* enable ana loopback */
 | ||
|     phy_txrx_loop_back_begin(0, TXRX_LOOP_BACK_GEODE);
 | ||
|     for(uint32_t i = 0; \
 | ||
|         i < sizeof(ate_geode_lpbk_gain_list)/sizeof(ate_loop_back_gain_list_t); i++)
 | ||
|     {
 | ||
| #if ATE_DEBUG_LEVEL >= 0
 | ||
|         iot_printf("att:%d,factor:%d,tx_pga:%d,rx_pgf:%d,rx_bq:%d,rx_pga:%d,rx_shift:%d,lna:%d\r\n", \
 | ||
|                 ate_geode_lpbk_gain_list[i].tx_tone_att, \
 | ||
|                 ate_geode_lpbk_gain_list[i].tx_factor, \
 | ||
|                 ate_geode_lpbk_gain_list[i].tx_pga_gain, \
 | ||
|                 ate_geode_lpbk_gain_list[i].rx_pgf_gain, \
 | ||
|                 ate_geode_lpbk_gain_list[i].rx_bq_gain, \
 | ||
|                 ate_geode_lpbk_gain_list[i].rx_pga_gain, \
 | ||
|                 ate_geode_lpbk_gain_list[i].rx_gain_shift, \
 | ||
|                 ate_geode_lpbk_gain_list[i].rx_lna_gain);
 | ||
| #endif
 | ||
|         /* tone atten and tx factor */
 | ||
|         phy_dfe_tone_att_cfg(0, ate_geode_lpbk_gain_list[i].tx_tone_att, 0);
 | ||
|         *(uint32_t *)0x51c00404=ate_geode_lpbk_gain_list[i].tx_tone_att;
 | ||
|         phy_tx_gain_factor_set(ate_geode_lpbk_gain_list[i].tx_factor);
 | ||
| 
 | ||
|         /* tx pga */
 | ||
|         phy_ana_rx_fe_gpga(ate_granite_lpbk_gain_list[i].tx_pga_gain);
 | ||
| 
 | ||
|         /* rx pgf bq pga*/
 | ||
|         phy_ana_rx_fe_gpgf(ate_granite_lpbk_gain_list[i].rx_pgf_gain);
 | ||
|         phy_ana_rx_fe_gbq(ate_granite_lpbk_gain_list[i].rx_bq_gain);
 | ||
|         phy_ana_rx_fe_gpga(ate_granite_lpbk_gain_list[i].rx_pga_gain);
 | ||
| 
 | ||
|         /* rx lna */
 | ||
|         phy_ana_rx_glna(ate_geode_lpbk_gain_list[i].rx_lna_gain);
 | ||
| 
 | ||
|         /* rx scale */
 | ||
|         if (ate_geode_lpbk_gain_list[i].rx_gain_shift > 0) {
 | ||
|             phy_gain_shift_set(0, 0, 0, ate_geode_lpbk_gain_list[i].rx_gain_shift);
 | ||
|         } else {
 | ||
|             ate_geode_lpbk_gain_list[i].rx_gain_shift = 0 - ate_geode_lpbk_gain_list[i].rx_gain_shift;
 | ||
|             phy_gain_shift_set(0, 0, 1, ate_geode_lpbk_gain_list[i].rx_gain_shift);
 | ||
|         }
 | ||
| 
 | ||
|         /* 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);
 | ||
| 
 | ||
|         /* get tone power */
 | ||
|         tone_idx = ATE_TONE_3M;
 | ||
|         csi_i = (int16_t)(*(csi_buf + tone_idx * 3) & 0xFFFF);
 | ||
|         csi_q = (int16_t)(*(csi_buf + tone_idx * 3) >> 16);
 | ||
|         golden_data = csi_i * csi_i + csi_q * csi_q;
 | ||
|         noise_data = 0;
 | ||
| 
 | ||
|         /* cal csi for every tone */
 | ||
|         for(tone_idx = 6; tone_idx < TONE_MAX_NUM; tone_idx++)
 | ||
|         {
 | ||
|             if(tone_idx != ATE_TONE_3M * 3){
 | ||
|                 csi_i = (int16_t)(*(csi_buf + tone_idx) & 0xFFFF);
 | ||
|                 csi_q = (int16_t)(*(csi_buf + tone_idx) >> 16);
 | ||
|                 noise_data += csi_i * csi_i + csi_q * csi_q;
 | ||
| #if 0
 | ||
|                 iot_printf("%d %d \n", tone_idx, csi_i * csi_i + csi_q * csi_q);
 | ||
| #endif
 | ||
|             } else {
 | ||
|                 csi_i = (int16_t)(*(csi_buf + tone_idx) & 0xFFFF);
 | ||
|                 csi_q = (int16_t)(*(csi_buf + tone_idx) >> 16);
 | ||
| #if 0
 | ||
|                 iot_printf("%d  %d \n", tone_idx, csi_i * csi_i + csi_q * csi_q);
 | ||
| #endif
 | ||
|             }
 | ||
|         }
 | ||
|         /* disable sw csi buf access */
 | ||
|         enable_sw_access_csi_buf(0);
 | ||
| 
 | ||
|         //iot_printf("golden_data %d noise_data %d \n", golden_data, noise_data);
 | ||
| 
 | ||
|         /* get AMP(-30dB) and SNR */
 | ||
|         glb_ate_info->csi_amp[8+i] = 10 * mlog10(golden_data/1000);
 | ||
|         glb_ate_info->csi_snr[8+i] = 10 * mlog10(golden_data/noise_data);
 | ||
| 
 | ||
|         if (glb_ate_info->csi_snr[8+i] >= 10) {
 | ||
|             iot_printf("[ATE]geode amp %d, snr %d, ###success###\r\n", \
 | ||
|                 glb_ate_info->csi_amp[8+i], glb_ate_info->csi_snr[8+i]);
 | ||
|         } else {
 | ||
|             iot_printf("[ATE]geode amp %d, snr %d, ###fail###\r\n", \
 | ||
|                 glb_ate_info->csi_amp[8+i], glb_ate_info->csi_snr[8+i]);
 | ||
|             ret = ERR_FAIL;
 | ||
|         }
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
|     /* recover to the state set in ana loopback */
 | ||
|     phy_txrx_loop_back_end();
 | ||
| 
 | ||
|     /* hw control tx rx */
 | ||
|     phy_ana_hw_en_bitmap(~0);
 | ||
| 
 | ||
|     return ret;
 | ||
| }
 | ||
| 
 | ||
| uint32_t ate_nf_test()
 | ||
| {
 | ||
|     uint32_t tmp = 0;
 | ||
|     uint32_t ret = ERR_OK;
 | ||
|     uint32_t valid_nf_num = 0;
 | ||
|     uint32_t nf_tmp = 0;
 | ||
|     uint32_t idx = 0;
 | ||
| 
 | ||
|     /* reset phy reg */
 | ||
|     phy_reset(PHY_RST_REASON_COLD);
 | ||
| 
 | ||
|     /* fix 60dB gain */
 | ||
|     phy_agc_gain_lvl_set(1, 60, -24, 0);
 | ||
| 
 | ||
|     /* disable packet detect timeout */
 | ||
|     tmp = PHY_RXTD_READ_REG(CFG_BB_PKT_TIME_OUT_ADDR);
 | ||
|     REG_FIELD_SET(SW_PKT_DET_TIME_OUT_DISABLE, tmp, 0);
 | ||
|     PHY_RXTD_WRITE_REG(CFG_BB_PKT_TIME_OUT_ADDR, tmp);
 | ||
| 
 | ||
|     /* disable reset by full */
 | ||
|     tmp = PHY_RXTD_READ_REG(CFG_BB_AGC_GAIN_LEVEL_ADDR);
 | ||
|     REG_FIELD_SET(SW_ADJ_REQ_DIS, tmp, 0);
 | ||
|     REG_FIELD_SET(SW_SAT_DIS, tmp, 0);
 | ||
|     PHY_RXTD_WRITE_REG(CFG_BB_AGC_GAIN_LEVEL_ADDR, tmp);
 | ||
| 
 | ||
|     /* ad/da bits shift */
 | ||
|     phy_gain_shift_set(0, 0, 0, 0);
 | ||
|     tmp = PHY_DFE_READ_REG(CFG_BB_AGC_SWCFG_EN_ADDR);
 | ||
|     REG_FIELD_SET(SW_AR1540_EN, tmp, 0x0);
 | ||
|     PHY_DFE_WRITE_REG(CFG_BB_AGC_SWCFG_EN_ADDR, tmp);
 | ||
| 
 | ||
|     /* config default RX ON regsiter */
 | ||
|     phy_agc_gain_adj_dis(0xE7FFC0FF);
 | ||
| 
 | ||
|     /* sw control tx rx */
 | ||
|     phy_ana_hw_en_bitmap(0);
 | ||
| 
 | ||
|     /* en adc and rx, disable dac and tx */
 | ||
|     phy_ana_top_tx_en(0);
 | ||
|     phy_ana_top_rx_en(1);
 | ||
|     phy_ana_top_adc_en(1);
 | ||
|     phy_ana_top_dac_en(0);
 | ||
|     phy_ana_top_enlic_rx_set(1);
 | ||
|     phy_ana_top_enlic_tx_set(0);
 | ||
| 
 | ||
|     /* force phy in rx state */
 | ||
|     phy_txrx_ovr_set(true, 1);
 | ||
|     /* enable geode */
 | ||
|     phy_phase_ovr_set(PHY_PHASE_OVR_A, true, PHY_TXRX_OVR_RX);
 | ||
|     phy_phase_ovr_set(PHY_PHASE_OVR_B, true, PHY_TXRX_OVR_RX);
 | ||
|     phy_phase_ovr_set(PHY_PHASE_OVR_C, true, PHY_TXRX_OVR_RX);
 | ||
| 
 | ||
|     /* disable tone */
 | ||
|     phy_dfe_tone_cfg(0, 0, 0);
 | ||
|     /* diable analog loopen */
 | ||
|     phy_ana_rx_pgfloop_set(0);
 | ||
| 
 | ||
|     /* rx pgf bq pga*/
 | ||
|     phy_ana_rx_fe_gpgf(1);
 | ||
|     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(0);
 | ||
|     phy_ana_rx_fe_byphpf_set(0);
 | ||
|     phy_ana_rx_fe_pwdpgf_offset_set(0);
 | ||
|     phy_ana_rx_fe_pwdpga_offset_set(0);
 | ||
| 
 | ||
|     glb_ate_info->nf = 0;
 | ||
|     /* nf get */
 | ||
|     for (idx = 0; idx < PHY_NF_RTY_CNT; idx++)
 | ||
|     {
 | ||
|         nf_tmp = phy_rx_nf_by_rxtd_get(14);
 | ||
|         /*121 is reset value, not valid value*/
 | ||
|         if (nf_tmp != PHY_NF_RST_VAL) {
 | ||
|             glb_ate_info->nf += nf_tmp;
 | ||
|             //iot_printf("[ATE]nf:%d\n", nf_tmp);
 | ||
|             valid_nf_num++;
 | ||
|         }
 | ||
|     }
 | ||
|     glb_ate_info->nf = glb_ate_info->nf/valid_nf_num;
 | ||
|     if (glb_ate_info->nf >= 30) {
 | ||
|         iot_printf("[ATE] current nf:%d ###fail###\n", glb_ate_info->nf);
 | ||
|         ret = ERR_FAIL;
 | ||
|     } else {
 | ||
|         iot_printf("[ATE] current nf:%d ###success###\n", glb_ate_info->nf);
 | ||
|     }
 | ||
|     /* hw control tx rx */
 | ||
|     phy_ana_hw_en_bitmap(~0);
 | ||
| 
 | ||
|     return ret;
 | ||
| }
 | ||
| 
 | ||
| void meter_test(void)
 | ||
| {
 | ||
|     int32_t doffset_avg = 0;
 | ||
|     int32_t dx_avg = 0;
 | ||
|     int32_t dy_avg = 0;
 | ||
|     float vref = 0;
 | ||
|     int32_t dc_offset = 0;
 | ||
|     int32_t dv = 0;
 | ||
|     int32_t ch1_adc3_v = 0;
 | ||
| 
 | ||
|     iot_printf("doffset_avg************0x%x\n", &glb_ate_info->doffset_avg);
 | ||
|     doffset_avg = sadc_ref_voltg_test(SADC_PHASE0, SADC_TSW_SEL_SCL_MUX_VCM_VCM, CP);
 | ||
|     glb_ate_info->doffset_avg = doffset_avg;
 | ||
| 
 | ||
|     /* cp test,single phase DIFF_CH10 */
 | ||
|     iot_printf("dx_avg*****************0x%x\n",&glb_ate_info->dx_avg);
 | ||
|     dx_avg = sadc_ref_voltg_test(SADC_PHASE0, SADC_TSW_SEL_SCL_MUX_DIFF_CH10, CP);
 | ||
|     glb_ate_info->dx_avg = dx_avg;
 | ||
| 
 | ||
|     /* cp test,single phase DIFF_CH32 */
 | ||
|     iot_printf("dy_avg****************0x%x\n",&glb_ate_info->dy_avg);
 | ||
|     dy_avg = sadc_ref_voltg_test(SADC_PHASE0, SADC_TSW_SEL_SCL_MUX_DIFF_CH32, CP);
 | ||
|     glb_ate_info->dy_avg = dy_avg;
 | ||
| 
 | ||
|     vref = (dx_avg - doffset_avg)/46786.0 + (dy_avg - doffset_avg)/23393.0;
 | ||
|     glb_ate_info->vref = vref;
 | ||
|     iot_printf("vref*****************0x%x\n", &glb_ate_info->vref);
 | ||
| 
 | ||
|     iot_printf("doffset_avg:%d dx_avg:%d dy_avg:%d vref:%f\n",doffset_avg,dx_avg,dy_avg,vref);
 | ||
| 
 | ||
|     /* ate test,VCM_VCM */
 | ||
|     dc_offset = sadc_ref_voltg_test(SADC_PHASE0, SADC_TSW_SEL_SCL_MUX_VCM_VCM, ATE);
 | ||
|     glb_ate_info->dc_offset = dc_offset;
 | ||
| 
 | ||
|     /* ch0 chopper 0x28 */
 | ||
|     uint32_t tmp = ANA_PMU_WRAP_RF_READ_REG(CFG_ANA_PMU_REG_CFG10_ADDR);
 | ||
|     REG_FIELD_SET(ICCAL, tmp, 0x10);
 | ||
|     ANA_PMU_WRAP_RF_WRITE_REG(CFG_ANA_PMU_REG_CFG10_ADDR, tmp);
 | ||
| 
 | ||
|     /* ate test,single phase CH1_ADC3 */
 | ||
|     iot_printf("CH1_ADC3\n");
 | ||
| 
 | ||
|     dv = sadc_ref_voltg_test(SADC_PHASE0, SADC_TSW_SEL_SCL_MUX_SING_CH3, ATE);
 | ||
|     iot_printf("%d\n",dv);
 | ||
| 
 | ||
|     ch1_adc3_v = dv - dc_offset;
 | ||
|     iot_printf("ch1_adc3_v:%d=%d - %d\n",ch1_adc3_v, dv, dc_offset);
 | ||
|     iot_printf("dc_offset*****************0x%x\n", &glb_ate_info->dc_offset);
 | ||
| 
 | ||
|     iot_printf("ch1_adc3_v*****************0x%x\n", glb_ate_info->ch1_adc3_v);
 | ||
| 
 | ||
|     /* ch0 chopper 0x28 */
 | ||
|     for(uint16_t j = 0; j < PMU_ICCAL_NUM; j++) {
 | ||
|         tmp = ANA_PMU_WRAP_RF_READ_REG(CFG_ANA_PMU_REG_CFG10_ADDR);
 | ||
|         REG_FIELD_SET(ICCAL, tmp, j);
 | ||
|         ANA_PMU_WRAP_RF_WRITE_REG(CFG_ANA_PMU_REG_CFG10_ADDR, tmp);
 | ||
|         dv = sadc_ref_voltg_test(SADC_PHASE0, SADC_TSW_SEL_SCL_MUX_SING_CH3, ATE);
 | ||
|         ch1_adc3_v = dv - dc_offset;
 | ||
|         glb_ate_info->ch1_adc3_v[j] = ch1_adc3_v;
 | ||
|         iot_printf("ICCAL + 1:%d=%d - %d\n", ch1_adc3_v, dv, dc_offset);
 | ||
|     }
 | ||
| }
 | ||
| /* main entry */
 | ||
| void ate_entry(void)
 | ||
| {
 | ||
|     uint32_t start_time = 0;
 | ||
|     uint32_t end_time = 0;
 | ||
|     uint64_t time_span = 0;
 | ||
| 
 | ||
|     uint32_t ret = ERR_OK;
 | ||
|     uint16_t tx_dc[4] = {0};
 | ||
|     uint16_t rx_dc[PHY_GAIN_STEP_MAX] = {0};
 | ||
| 
 | ||
|     start_time = RGF_MAC_READ_REG(CFG_RD_NTB_ADDR);
 | ||
| 
 | ||
| #if HW_PLATFORM > HW_PLATFORM_SIMU
 | ||
| #if EDA_SIMU_SUPPORT != 1
 | ||
|     for(volatile uint32_t i = 0; i < 5000; i++);
 | ||
|     /* serial init */
 | ||
|     dbg_uart_init();
 | ||
|     iot_printf("ate_test begin...\n");
 | ||
| #endif
 | ||
| #endif
 | ||
| 
 | ||
|     ate_init();
 | ||
| 
 | ||
|     /* efuse chip-id nad version */
 | ||
|     glb_ate_info->result = 0;
 | ||
|     glb_ate_info->ret_flag = 0;
 | ||
|     glb_ate_info->rsv[0] = 0x5a5a5a5a;
 | ||
|     glb_ate_info->rsv[1] = 0x5a5a5a5a;
 | ||
|     glb_ate_info->rsv[2] = 0x5a5a5a5a;
 | ||
|     glb_ate_info->rsv[3] = 0x5a5a5a5a;
 | ||
| 
 | ||
|     /* tx dc calibration */
 | ||
|     ret = tx_dc_calibration(tx_dc);
 | ||
|     if (ret == ERR_OK) {
 | ||
|         os_mem_cpy(glb_ate_info->tx_dc, tx_dc, sizeof(tx_dc));
 | ||
|     } else {
 | ||
|         glb_ate_info->ret_flag |= ERR_BIT(0);
 | ||
|     }
 | ||
| 
 | ||
|     /* rx dc calibration */
 | ||
|     ret = rx_dc_calibration(rx_dc);
 | ||
|     if (ret == ERR_OK) {
 | ||
|         os_mem_cpy(glb_ate_info->rx_dc, rx_dc, sizeof(rx_dc));
 | ||
|     } else {
 | ||
|         glb_ate_info->ret_flag |= ERR_BIT(1);
 | ||
|     }
 | ||
| 
 | ||
|     /* granite loopback */
 | ||
|     ret = mac_granite_loop_back();
 | ||
|     if (ret != ERR_OK) {
 | ||
|         glb_ate_info->ret_flag |= ERR_BIT(2);
 | ||
|     }
 | ||
| 
 | ||
|     /* geode loopback */
 | ||
|     ret = mac_geode_loop_back();
 | ||
|     if (ret != ERR_OK) {
 | ||
|         glb_ate_info->ret_flag |= ERR_BIT(3);
 | ||
|     }
 | ||
| 
 | ||
|     /* rx bandwidth filter calibration */
 | ||
|     phy_rx_bw_filter(RX_BW_LIST_BAND0_12M);
 | ||
|     /* reset phy */
 | ||
|     phy_reset(PHY_RST_REASON_WARM);
 | ||
|     phy_rx_bw_filter(RX_BW_LIST_BAND1_5P6M);
 | ||
| 
 | ||
|     /* nf test */
 | ||
|     ret = ate_nf_test();
 | ||
|     if (ret != ERR_OK) {
 | ||
|         glb_ate_info->ret_flag |= ERR_BIT(4);
 | ||
|     }
 | ||
| 
 | ||
|     meter_test();
 | ||
| 
 | ||
|     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;
 | ||
|     }
 | ||
|     iot_printf("[ATE]total time: %llu us\n", time_span/TICKS_US);
 | ||
|     if (!glb_ate_info->ret_flag) {
 | ||
|         glb_ate_info->result = true;
 | ||
|         iot_printf("ATE test pass!\n");
 | ||
|     } else {
 | ||
|        glb_ate_info->result = 0x55;
 | ||
|        iot_printf("glb_ate_info->ret_flag: %d\n",glb_ate_info->ret_flag);
 | ||
|        iot_printf("ATE test fail!\n");
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| int main(void) {
 | ||
| 
 | ||
|     ate_entry();
 | ||
| 
 | ||
|     return 0;
 | ||
| }
 |