Files
kunlun/plc/halphy/phy_rf_init.c
2024-09-28 14:24:04 +08:00

496 lines
13 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 "phy_rf_init.h"
#include "iot_config.h"
#include "iot_io_api.h"
#include "iot_board_api.h"
#include "iot_errno_api.h"
#include "iot_oem_api.h"
#include "iot_system.h"
#include "iot_cal_data.h"
#include "os_utils.h"
#include "hw_reg_api.h"
#include "phy_rf_chn.h"
#include "ahb.h"
#include "gpio_mtx.h"
#include "plc_const.h"
#include "phy_txrx_pwr.h"
#include "phy_bb.h"
#include "iot_efuse.h"
#if (HPLC_RF_DEV_SUPPORT && (HW_PLATFORM != HW_PLATFORM_SIMU))
#include "rfplc_reg_base.h"
#include "wphy_reg.h"
#include "mac_sys_reg.h"
#include "wphy_reg.h"
#include "mac_rf_isr.h"
#include "mac_rf_common_hw.h"
#include "phy_rf_chn.h"
#include "rf_hw_tonemap.h"
#include "gpio_mtx.h"
static uint32_t phy_rf_wait_bbcpu_ready()
{
#define WAIT_READY_TIMEOUT 37500000 // 1.5S * 1000 * 25
uint32_t start_ntb, cur_ntb, time_span;
/* wait bbcpu ready */
start_ntb = RGF_MAC_READ_REG(CFG_RD_LOCAL_TMR_ADDR);
do {
cur_ntb = RGF_MAC_READ_REG(CFG_RD_LOCAL_TMR_ADDR);
time_span = cur_ntb - start_ntb;
} while (!mac_rf_get_bbcpu_sts() && time_span < WAIT_READY_TIMEOUT);
if (!mac_rf_get_bbcpu_sts()) {
iot_printf("bbcpu init fail!\n");
IOT_ASSERT(0);
return 0;
}
return 1;
}
void phy_rf_load_cal_cfg(void)
{
uint32_t ret;
uint8_t i;
uint8_t bw_sel_en;
uint16_t special_tx_lvdos = 300;
uint16_t special_tx_scale = 0x80;
uint16_t bw_sel;
iot_cal_data_rf_ver_phy_txiqm_t *cal_iqm;
iot_cal_data_rf_phy_txf_t *cal_txf;
uint8_t tx_i_mag, tx_q_mag, tx_i_phase, tx_q_phase;
int8_t tx_i_dc, tx_q_dc;
ret = iot_cal_data_get_rf_phy_txiqm_cali(&cal_iqm);
mac_rf_set_tx_special_ldovs(special_tx_lvdos);
mac_rf_set_tx_special_scale(special_tx_scale);
if (ret == ERR_OK) {
mac_rf_set_tx_dc_cali((uint8_t)cal_iqm->tx_i_dc,
(uint8_t)cal_iqm->tx_q_dc);
mac_rf_set_tx_iqm_cali(cal_iqm->tx_i_mag, cal_iqm->tx_q_mag);
mac_rf_set_tx_iqp_cali(cal_iqm->tx_i_phase, cal_iqm->tx_q_phase);
if (phy_rf_check_rf_version(cal_iqm->rf_ver)) {
mac_rf_set_rf_ver(cal_iqm->rf_ver);
}
iot_printf("%s ok, src:flash, tx_i_dc:%d, tx_q_dc:%d, tx_i_mag:%lu, "
"tx_q_mag:%lu, tx_i_phase:%lu, tx_q_phase: %lu, rf_ver:%d\n",
__FUNCTION__, cal_iqm->tx_i_dc, cal_iqm->tx_q_dc, cal_iqm->tx_i_mag,
cal_iqm->tx_q_mag, cal_iqm->tx_i_phase, cal_iqm->tx_q_phase,
cal_iqm->rf_ver);
goto next_1;
}
ret = iot_efuse_get_rf_tx_iqm_dc_calib_info(&tx_i_mag, &tx_q_mag,
&tx_i_phase, &tx_q_phase, &tx_i_dc, &tx_q_dc);
if (ret == ERR_OK) {
mac_rf_set_tx_dc_cali((uint8_t)tx_i_dc, (uint8_t)tx_q_dc);
mac_rf_set_tx_iqm_cali(tx_i_mag, tx_q_mag);
mac_rf_set_tx_iqp_cali(tx_i_phase, tx_q_phase);
iot_printf("%s ok src:efuse, tx_i_dc:%d, tx_q_dc:%d, tx_i_mag:%lu, "
"tx_q_mag:%lu, tx_i_phase:%lu, tx_q_phase: %lu, rf_ver:%d\n",
__FUNCTION__, tx_i_dc, tx_q_dc, tx_i_mag, tx_q_mag,
tx_i_phase, tx_q_phase, RF_VER_3);
} else {
mac_rf_set_tx_dc_cali(0, 0);
mac_rf_set_tx_iqm_cali(0, 0);
mac_rf_set_tx_iqp_cali(0, 0);
iot_printf("%s tx iqm fail...\n", __FUNCTION__);
}
next_1:
ret = iot_cal_data_get_rf_phy_txf_cali(&cal_txf);
if (ret == ERR_OK) {
for (i = RF_OPTION_1; i <= RF_OPTION_MAX; i++) {
if (cal_txf->valid_mask & (1 << (i - 1))) {
bw_sel_en = 1;
bw_sel = cal_txf->bw_sel_value[i - 1];
} else {
bw_sel_en = 0;
bw_sel = 0;
}
mac_rf_set_tx_filter_cali(i, bw_sel_en, bw_sel);
iot_printf("%s ok, option %lu, en %lu, bw_sel %lu\n",
__FUNCTION__, i, bw_sel_en, bw_sel);
}
} else {
mac_rf_set_tx_filter_cali(RF_OPTION_1, 0, 0);
mac_rf_set_tx_filter_cali(RF_OPTION_2, 0, 0);
mac_rf_set_tx_filter_cali(RF_OPTION_3, 0, 0);
iot_printf("%s tx txf fail...\n", __FUNCTION__);
}
/* set user type */
mac_rf_set_user_type(iot_oem_get_user_type());
/* apply oem ppm to rf */
mac_rf_set_wphy_ppm(-phy_get_cal_ppm_in_pib() << PLC_NTB_PPM_SHIFT);
if (iot_oem_get_module_type() != MODULE_TYPE_CCO) {
mac_rf_set_sta_sel(1);
}
/* TODO:
* load rx iqm calibration data from efuse */
}
/* indicate if the first init rf phy or not */
static uint8_t phy_rf_first_init = 1;
/* record phy rf start ntb */
static uint32_t phy_rf_start_ntb;
void phy_rf_wait_init()
{
#define SET_OPTION_TIMEOUT 25000000 // 1S * 1000 * 25
uint32_t cur_ntb, time_span;
/* wait set option complete */
do {
cur_ntb = RGF_MAC_READ_REG(CFG_RD_LOCAL_TMR_ADDR);
time_span = cur_ntb - phy_rf_start_ntb;
} while (mac_rf_get_option_sts() && time_span < SET_OPTION_TIMEOUT);
if (mac_rf_get_option_sts()) {
iot_printf("%s, set option fail\n", __FUNCTION__);
}
}
void phy_rf_in_check(void)
{
uint32_t chip_id;
chip_id = iot_efuse_get_chip_id();
switch (chip_id) {
case CHIP_ID_HZ3201_RF_V1A:
case CHIP_ID_HZ3211_RF_V1A:
{
mac_rf_set_rf_in(1);
break;
}
default:
{
mac_rf_set_rf_in(0);
break;
}
}
}
void phy_rf_init(uint32_t proto, uint32_t option, uint32_t channel,
uint32_t sync_init, uint32_t auto_rxdc, uint32_t auto_txdc)
{
IOT_ASSERT(option < PHY_RF_OPTION_MAX && proto <= PLC_PROTO_TYPE_RAWDATA);
uint32_t cert_flag = 0, cert_mode = 0, flag16com = 0, rf_ver = 0;
uint32_t rx_cali_flag = 0;
uint8_t rx_dc_i = 0, rx_dc_q = 0, tx_dc_i, tx_dc_q;
int8_t tx_power = RF_TX_PWR_INVALID;
uint8_t rf_in = 0;
/* if not the first time to init rf phy */
if (!phy_rf_first_init) {
/* restore cert config */
cert_flag = mac_rf_get_cert_flag();
cert_mode = mac_rf_get_cert_mode();
flag16com = mac_rf_get_cert_16qam_flag();
rf_in = mac_rf_is_rf_in();
if (mac_rf_get_target_tx_power(&tx_power)) {
/* if not init tx power, set default power */
phy_rf_get_power(NULL, NULL, &tx_power, NULL);
}
rf_ver = mac_rf_get_rf_ver();
/* restore rx dc configration */
rx_cali_flag = mac_rf_get_rx_dc_loopback_clibr_flag();
mac_rf_get_auto_rxdc_iq_value(&rx_dc_i, &rx_dc_q);
mac_rf_get_tx_dc_cali(&tx_dc_i, &tx_dc_q);
}
/* ahb init and reset */
ahb_rfmac_disable();
ahb_rfmac_reg_disable();
ahb_rfmac_enable();
ahb_rfmac_reg_enable();
ahb_rfmac_reset();
ahb_rfmac_reg_reset();
ahb_rfplc_phy_disable();
ahb_rfplc_phy_reg_disable();
ahb_rfplc_ana_disable();
ahb_rfplc_phy_enable();
ahb_rfplc_phy_reg_enable();
ahb_rfplc_ana_enable();
ahb_rfplc_phy_reset();
ahb_rfplc_phy_reg_reset();
ahb_rfplc_ana_reset();
/* enable wmac */
mac_rf_use_wmac_enable(HPLC_RF_WMAC_ENABLE);
#if (IOT_DTEST_ONLY_SUPPORT != 1)
/* get rf spi */
uint8_t clk = iot_board_get_gpio(GPIO_SPI_RF_CLK);
uint8_t cs = iot_board_get_gpio(GPIO_SPI_RF_CS);
uint8_t miso = iot_board_get_gpio(GPIO_SPI_RF_MISO);
uint8_t mosi = iot_board_get_gpio(GPIO_SPI_RF_MOSI);
#else
/* rf mac dtest */
#if HW_PLATFORM == HW_PLATFORM_FPGA
uint8_t clk = 9;
uint8_t cs = 12;
uint8_t miso = 11;
uint8_t mosi = 10;
#else
uint8_t clk = 12;
uint8_t cs = 9;
uint8_t miso = 10;
uint8_t mosi = 11;
for (uint32_t wphy_gpio = 42; wphy_gpio < 60; wphy_gpio++) {
gpio_pin_select(wphy_gpio, 1);
}
#endif
#endif
/* init rf spi gpio */
mac_rf_set_spi_gpio(clk, cs, mosi, miso);
/* load rf calibration config */
phy_rf_load_cal_cfg();
if (!phy_rf_first_init) {
mac_rf_set_rf_ver(rf_ver);
mac_rf_set_rf_in(rf_in);
} else {
phy_rf_in_check();
}
/* config band select */
mac_rf_set_band_sel(phy_rf_get_band_sel());
/* bbcpu start */
extern int bb_cpu_start();
bb_cpu_start();
if (!phy_rf_wait_bbcpu_ready()) {
return;
}
if (HPLC_RF_SUPPORT_AUTO_CALIBR_TX_DC) {
if (!auto_txdc && !phy_rf_first_init) {
mac_rf_set_tx_dc_loopback_clibr_en(0);
mac_rf_set_tx_dc_cali(tx_dc_i, tx_dc_q);
} else if (auto_txdc) {
mac_rf_set_tx_dc_loopback_clibr_en(1);
}
}
/* recover record value */
if (phy_rf_first_init) {
/* is first time to init rf */
phy_rf_set_init_power();
phy_rf_first_init = 0;
} else {
/* recover cert config */
mac_rf_set_cert_flag(cert_flag);
mac_rf_set_cert_mode(cert_mode);
mac_rf_set_cert_16qam_flag(flag16com);
mac_rf_set_target_tx_power(tx_power);
}
/* auto clibration enable or not */
mac_rf_set_rx_dc_loopback_clibr_en(HPLC_RF_SUPPORT_AUTO_CALIBR_RX_DC);
if (rx_cali_flag) {
if (auto_rxdc) {
mac_rf_set_rx_dc_loopback_clibr_flag(0);
} else {
mac_rf_set_rx_dc_loopback_clibr_flag(1);
mac_rf_set_auto_rxdc_iq_value(rx_dc_i, rx_dc_q);
}
} else if (!auto_rxdc) {
mac_rf_set_rx_dc_loopback_clibr_en(0);
}
/* fl init */
phy_rf_fl_init(option);
/* first set channel */
IOT_ASSERT(channel < phy_rf_get_channel_id_max(option));
/* set proto */
mac_rf_set_proto(proto);
/* set channel */
mac_rf_set_tobe_channel_id(channel);
/* set option */
mac_rf_set_option(option);
mac_rf_set_sw_irq_to_bbcpu(RF_MAC_SW_ISR_BB_INIT);
phy_rf_start_ntb = RGF_MAC_READ_REG(CFG_RD_LOCAL_TMR_ADDR);
if (sync_init) {
phy_rf_wait_init();
}
}
void phy_rf_deinit(void)
{
/* bbcpu stop */
extern int bb_cpu_stop();
bb_cpu_stop();
/* ahb init and reset */
ahb_rfmac_disable();
ahb_rfmac_reg_disable();
ahb_rfplc_phy_disable();
ahb_rfplc_phy_reg_disable();
ahb_rfplc_ana_disable();
}
uint8_t phy_rf_is_run(void)
{
extern uint8_t bb_cpu_is_run();
return bb_cpu_is_run();
}
void phy_rf_set_channel(uint8_t channel)
{
#define SET_CHANNEL_TIMEOUT 25000000 // 1S * 1000 * 25
uint32_t start_ntb, cur_ntb, time_span;
uint32_t option = mac_rf_get_option();
uint32_t channel_max = phy_rf_get_channel_id_max(option);
IOT_ASSERT(channel < channel_max);
mac_rf_set_tobe_channel_id(channel);
mac_rf_set_sw_irq_to_bbcpu(RF_MAC_SW_ISR_SET_CHANNEL);
/* wait set channel complete */
start_ntb = RGF_MAC_READ_REG(CFG_RD_LOCAL_TMR_ADDR);
do {
cur_ntb = RGF_MAC_READ_REG(CFG_RD_LOCAL_TMR_ADDR);
time_span = cur_ntb - start_ntb;
} while (mac_rf_get_channel_sts() && time_span < SET_CHANNEL_TIMEOUT);
if (mac_rf_get_channel_sts()) {
iot_printf("%s, set channel fail\n", __FUNCTION__);
}
}
void phy_rf_reset()
{
// TODO: SOC supply register to hard reset phy.
return;
}
void phy_rf_new_cfg_apply()
{
/* rf phy init, plc cpu and bbcpu async init, rf rxdc enable */
phy_rf_init(phy_proto_type_get(), mac_rf_get_option(),
mac_rf_get_tobe_set_channel_id(), 1, 0, 0);
/* rf isr init */
mac_rf_isr_init(mac_rf_get_dsr_callback());
/* init rf pdev */
extern uint32_t mac_rf_pdev_init(pdevid_t pdev_id);
mac_rf_pdev_init(RF_PDEV_ID);
/* start isr */
mac_rf_isr_start();
}
void phy_record_dbg_cnt()
{
/* recover dbg cnt */
mac_rf_record_dbg_cnt();
}
void phy_recover_dbg_cnt()
{
/* recover dbg cnt */
mac_rf_recover_dbg_cnt();
}
void phy_rf_set_ps_idle(uint32_t ps_on)
{
mac_rf_set_bb_ps_idle(ps_on);
mac_rf_set_sw_irq_to_bbcpu(RF_MAC_SW_ISR_SET_PS_IDLE);
}
void phy_rf_set_init_power()
{
uint32_t power = RF_TX_PWR_INVALID;
int8_t def_pwr, full_pwr;
phy_rf_get_power(NULL, NULL, &def_pwr, &full_pwr);
if (!phy_get_pwr_ctl_en()) {
/* LP */
power = def_pwr;
} else {
/* FULL POWER */
power = full_pwr;
}
mac_rf_set_target_tx_power(power);
}
#else /* (HPLC_RF_DEV_SUPPORT && (HW_PLATFORM != HW_PLATFORM_SIMU)) */
void phy_rf_wait_init()
{
}
void phy_rf_init(uint32_t proto, uint32_t option, uint32_t channel,
uint32_t sync_init, uint32_t auto_rxdc, uint32_t auto_txdc)
{
(void)proto;
(void)option;
(void)channel;
(void)sync_init;
(void)auto_rxdc;
(void)auto_txdc;
}
void phy_rf_deinit()
{
}
void phy_rf_set_channel(uint8_t channel)
{
(void)channel;
}
void phy_rf_reset()
{
}
void phy_rf_new_cfg_apply()
{
}
void phy_recover_dbg_cnt()
{
}
void phy_record_dbg_cnt()
{
}
void phy_rf_load_cal_cfg(void)
{
}
void phy_rf_set_ps_idle(uint32_t ps_on)
{
(void)ps_on;
}
void phy_rf_set_init_power()
{
}
void phy_rf_in_check(void)
{
}
#endif /* (HPLC_RF_DEV_SUPPORT && (HW_PLATFORM != HW_PLATFORM_SIMU)) */