668 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			668 lines
		
	
	
		
			21 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 "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; | |||
|  | } |