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

680 lines
20 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 "hw_phy_init.h"
#include "hw_tonemask.h"
#include "phy_ana.h"
#include "plc_fr.h"
#if HW_PLATFORM > HW_PLATFORM_SIMU
#include "dbg_io.h"
#endif
#include "plc_utils.h"
#include "phy_bb.h"
#include "hw_desc.h"
#include "hw_gain_table.h"
#include "mac_sys_reg.h"
#include "hw_reg_api.h"
#include "phy_reg.h"
#include "iot_io_api.h"
#include "plc_protocol.h"
#include "gpio_mtx.h"
#include "phy_cal.h"
#include "phy_dfe_reg.h"
#include "iot_errno_api.h"
#include "iot_share_task.h"
#include "hw_phy_api.h"
#include "phy_isr.h"
#include "phy_nf.h"
#include "phy_pm.h"
#include "phy_status.h"
#include "phy_overstress.h"
#include "phy_cfg.h"
#include "phy_mix.h"
#include "phy_txrx_pwr.h"
#include "iot_config.h"
#include "phy_phase.h"
#include "clk.h"
#include "phy_chn.h"
#include "phy_data_ckb.h"
#include "iot_cli.h"
#include "iot_system.h"
#include "phy_geode_gpio.h"
#include "phy_temperature.h"
#include "iot_clock.h"
#include "os_utils.h"
#include "iot_gpio_api.h"
#include "iot_board_api.h"
/* load band table by default */
void phy_tone_band_init(uint32_t mac_typ)
{
/* multi band from default tbl */
phy_rate_band_set(0, HW_FULL_BAND,
all_mask_band_table_r0_full.fc_sym_num,
all_mask_band_table_r0_full.start_tone,
all_mask_band_table_r0_full.end_tone);
phy_rate_band_set(0, HW_LOW_BAND,
all_mask_band_table_r0_low.fc_sym_num,
all_mask_band_table_r0_low.start_tone,
all_mask_band_table_r0_low.end_tone);
phy_rate_band_set(0, HW_HIGH_BAND,
all_mask_band_table_r0_high.fc_sym_num,
all_mask_band_table_r0_high.start_tone,
all_mask_band_table_r0_high.end_tone);
phy_rate_band_set(1, HW_FULL_BAND,
all_mask_band_table_r1_full.fc_sym_num,
all_mask_band_table_r1_full.start_tone,
all_mask_band_table_r1_full.end_tone);
phy_rate_band_set(1, HW_LOW_BAND,
all_mask_band_table_r1_low.fc_sym_num,
all_mask_band_table_r1_low.start_tone,
all_mask_band_table_r1_low.end_tone);
phy_rate_band_set(1, HW_HIGH_BAND,
all_mask_band_table_r1_high.fc_sym_num,
all_mask_band_table_r1_high.start_tone,
all_mask_band_table_r1_high.end_tone);
phy_vld_tone_num_set(0, HW_FULL_BAND,
all_mask_band_table_r0_full.valid_tone_number);
phy_vld_tone_num_set(0, HW_LOW_BAND,
all_mask_band_table_r0_low.valid_tone_number);
phy_vld_tone_num_set(0, HW_HIGH_BAND,
all_mask_band_table_r0_high.valid_tone_number);
phy_vld_tone_num_set(1, HW_FULL_BAND,
all_mask_band_table_r1_full.valid_tone_number);
phy_vld_tone_num_set(1, HW_LOW_BAND,
all_mask_band_table_r1_low.valid_tone_number);
phy_vld_tone_num_set(1, HW_HIGH_BAND,
all_mask_band_table_r1_high.valid_tone_number);
if(mac_typ == PLC_PROTO_TYPE_SG)
{
/* short band for mix mode*/
phy_short_band_set(1, 80, 743);
phy_short_vld_tone_num_set(664);
}
}
/* config start/end/valid tone and fc num */
void phy_band_init(uint32_t mac_typ, uint32_t band_id)
{
phy_tone_band_init(mac_typ);
(void)band_id;
}
/* keep sync the old version, maybe delete later */
void phy_band_tbl_load(plc_band_table_t *table)
{
#if HW_PLATFORM != HW_PLATFORM_SIMU
if (!table) {
return;
}
/* write the band table into reg */
RGF_MAC_WRITE_REG(CFG_BAND_PTR_ADDR, (uint32_t)table);
#else
(void)table;
#endif
return;
}
uint32_t phy_start_end_tone_get(
uint32_t mac_proto,
uint32_t range_id,
uint32_t band_id,
plc_tone_mask_id mask_id,
uint16_t *band_start_tone,
uint16_t *band_end_tone,
uint8_t *fc_sym)
{
uint32_t ret = ERR_OK;
uint16_t valid_tone_num = 0;
/* get band info */
ret = phy_band_info_get_by_id(
mac_proto,
range_id,
band_id,
&valid_tone_num,
fc_sym,
band_start_tone,
band_end_tone);
/* check tone mask id */
if (range_id == IOT_SUPPORT_PROTO_GP_BAND) {
/* check mask id for each band id */
if (mask_id != TONE_MASK_ID_GP && mask_id != TONE_MASK_ID_NULL) {
ret = ERR_FAIL;
}
} else if (range_id == IOT_SUPPORT_PROTO_SG_NSG_BAND) {
if (band_id == IOT_SUPPORT_TONE_80_490) {
/* check mask id for each band id */
if (mask_id != TONE_MASK_ID_SG0 && mask_id != TONE_MASK_ID_NULL) {
ret = ERR_FAIL;
}
} else if (band_id == IOT_SUPPORT_TONE_100_230) {
/* check mask id for each band id */
if (mask_id != TONE_MASK_ID_SG1 && mask_id != TONE_MASK_ID_NULL) {
ret = ERR_FAIL;
}
} else if (band_id == IOT_SUPPORT_TONE_32_120) {
/* check mask id for each band id */
if (mask_id != TONE_MASK_ID_SG2 && mask_id != TONE_MASK_ID_NULL) {
ret = ERR_FAIL;
}
} else if (band_id == IOT_SUPPORT_TONE_72_120) {
/* check mask id for each band id */
if (mask_id != TONE_MASK_ID_SG3 && mask_id != TONE_MASK_ID_NULL) {
ret = ERR_FAIL;
}
} else if (band_id == IOT_SUPPORT_TONE_200_1000) {
/* check mask id for each band id */
if (mask_id != TONE_MASK_ID_CUS && mask_id != TONE_MASK_ID_NULL) {
ret = ERR_FAIL;
}
}
} else {
/* check mask id for each band id */
if (mask_id != TONE_MASK_ID_SG0 && mask_id != TONE_MASK_ID_SG1 &&
mask_id != TONE_MASK_ID_NULL) {
ret = ERR_FAIL;
}
}
/* check valid */
if(ret != ERR_OK) {
*band_start_tone = 0;
*band_end_tone = 0;
iot_printf("%s: tome mask id not exit, use default!\n", __FUNCTION__);
}
return ret;
}
uint32_t phy_band_tbl_init(const plc_tonemask_table *tone_msk_ptr,
uint32_t band_start_tone, uint32_t band_end_tone, uint32_t fc_sym)
{
if (band_start_tone == 0 || band_end_tone == 0) {
/* full band */
init_band_table(&all_mask_band_table_r0_full, HW_FULL_BAND,
tone_msk_ptr, all_mask_band_table_r0_full.fc_sym_num,
all_mask_band_table_r0_full.start_tone,
all_mask_band_table_r0_full.end_tone);
/* low band */
init_band_table(&all_mask_band_table_r0_low, HW_LOW_BAND, tone_msk_ptr,
all_mask_band_table_r0_low.fc_sym_num,
all_mask_band_table_r0_low.start_tone,
all_mask_band_table_r0_low.end_tone);
/* high band */
init_band_table(&all_mask_band_table_r0_high, HW_HIGH_BAND,
tone_msk_ptr, all_mask_band_table_r0_high.fc_sym_num,
all_mask_band_table_r0_high.start_tone,
all_mask_band_table_r0_high.end_tone);
/* full band */
init_band_table(&all_mask_band_table_r1_full, HW_FULL_BAND,
tone_msk_ptr, all_mask_band_table_r1_full.fc_sym_num,
all_mask_band_table_r1_full.start_tone,
all_mask_band_table_r1_full.end_tone);
/* low band */
init_band_table(&all_mask_band_table_r1_low, HW_LOW_BAND, tone_msk_ptr,
all_mask_band_table_r1_low.fc_sym_num,
all_mask_band_table_r1_low.start_tone,
all_mask_band_table_r1_low.end_tone);
/* high band */
init_band_table(&all_mask_band_table_r1_high, HW_HIGH_BAND,
tone_msk_ptr, all_mask_band_table_r1_high.fc_sym_num,
all_mask_band_table_r1_high.start_tone,
all_mask_band_table_r1_high.end_tone);
} else {
/* full band */
init_band_table(&all_mask_band_table_r0_full, HW_FULL_BAND,
tone_msk_ptr, fc_sym, band_start_tone, band_end_tone);
/* low band */
init_band_table(&all_mask_band_table_r0_low, HW_LOW_BAND, tone_msk_ptr,
fc_sym, band_start_tone, band_end_tone);
/* high band */
init_band_table(&all_mask_band_table_r0_high, HW_HIGH_BAND,
tone_msk_ptr, fc_sym, band_start_tone, band_end_tone);
/* full band */
init_band_table(&all_mask_band_table_r1_full, HW_FULL_BAND,
tone_msk_ptr, fc_sym, band_start_tone, band_end_tone);
/* low band */
init_band_table(&all_mask_band_table_r1_low, HW_LOW_BAND, tone_msk_ptr,
fc_sym, band_start_tone, band_end_tone);
/* high band */
init_band_table(&all_mask_band_table_r1_high, HW_HIGH_BAND,
tone_msk_ptr, fc_sym, band_start_tone, band_end_tone);
}
return 0;
}
/* load range table to band table */
void phy_multi_band_tbl_update(uint32_t range_id, uint32_t band_id)
{
const plc_phy_band_table_t *band_tab;
/* SR config */
if (range_id == IOT_SUPPORT_PROTO_SG_NSG_BAND) {
phy_get_plc_nsg_band_tab_info(&band_tab);
#if SUPPORT_SOUTHERN_POWER_GRID
if (IOT_SUPPORT_TONE_MULTI_BAND021 == band_id) {
all_mask_band_table_r0_full = band_tab[2].band_info;
all_mask_band_table_r0_low = band_tab[2].band_info;
all_mask_band_table_r0_high = band_tab[1].band_info;
} else {
/* must specail multiband */
IOT_ASSERT(0);
}
#elif SUPPORT_SMART_GRID
if (IOT_SUPPORT_TONE_MULTI_BAND021 == band_id) {
all_mask_band_table_r0_full = band_tab[0].band_info;
all_mask_band_table_r0_low = band_tab[2].band_info;
all_mask_band_table_r0_high = band_tab[1].band_info;
} else {
/* must specail multiband */
IOT_ASSERT(0);
}
#endif
} else if (range_id == IOT_SUPPORT_PROTO_GP_BAND) {
phy_get_plc_gp_band_tab_info(&band_tab);
// TODO: maybe use SUPPORT_GREEN_PHY manage the code
all_mask_band_table_r0_full = band_tab[0].band_info;
all_mask_band_table_r0_low = band_tab[1].band_info;
/* gp only has 2 bands used, to prevent array index out of bounds */
all_mask_band_table_r0_high = band_tab[1].band_info;
} else {
(void)band_id;
IOT_ASSERT(0);
}
}
void phy_band_info_update(uint32_t mac_proto,
uint32_t range_id,
uint32_t band_id,
plc_tone_mask_id mask_id)
{
uint16_t band_start_tone = 0;
uint16_t band_end_tone = 0;
uint8_t fc_sym = 0;
const plc_tonemask_table *tone_msk_ptr = NULL;
/* update glb config */
phy_proto_type_set(mac_proto);
phy_band_id_set(band_id);
phy_mask_id_set(mask_id);
/* get tone */
if(band_id >= IOT_SUPPORT_TONE_MULTI_BAND021) {
/* update all band */
phy_multi_band_tbl_update(range_id, band_id);
} else {
phy_start_end_tone_get(
mac_proto,
range_id,
band_id,
mask_id,
&band_start_tone,
&band_end_tone,
&fc_sym);
}
/* mask id */
tone_msk_ptr = phy_tone_mask_ptr_get(mask_id);
/* phy band init */
phy_band_tbl_init(tone_msk_ptr, band_start_tone, band_end_tone, fc_sym);
/* band reg init */
phy_band_init(mac_proto, band_id);
/* new sg support */
if (mac_proto == PLC_PROTO_TYPE_SG) {
/* TODO Note:
standard smart grid must < 512 and set flag en
iot can use any band and donnot care flag or not
*/
if (all_mask_band_table_r0_full.end_tone > 512) {
phy_new_sg_en(false);
} else {
phy_new_sg_en(true);
}
}
#if PLC_MAC_RX_DEBUG_LOG
/* print the band table inited */
print_band_table(&all_mask_band_table_r0_full);
print_band_table(&all_mask_band_table_r0_low);
print_band_table(&all_mask_band_table_r0_high);
print_band_table(&all_mask_band_table_r1_full);
print_band_table(&all_mask_band_table_r1_low);
print_band_table(&all_mask_band_table_r1_high);
#endif
#if PLC_MEM_ALLOC_STAT
iot_printf("band table = %d bytes, tone mask table = %d bytes\n",
sizeof(all_mask_band_table_r0_full), sizeof(all_mask_tone_mask_table));
#endif
/* becareful the seq of these table load */
phy_band_tbl_load(&all_mask_band_table_r0_full);
phy_tone_mask_amp_phase_tab_load(&all_mask_amp_phase_table, mask_id,
mac_proto);
phy_gain_tab_load(all_mask_gain_table);
/* update tobe config */
phy_proto_type_to_set(mac_proto);
phy_band_id_to_set(band_id);
phy_mask_id_to_set(mask_id);
/* update tone detect range */
phy_update_tone_det_range();
/* band rate tbl range init */
phy_ra_tbl_band_range_init();
/* band filter select cfg */
#if (PLC_SUPPORT_BAND_FILTER_SELECT && IOT_DTEST_ONLY_SUPPORT == 0)
if (mac_proto == PLC_PROTO_TYPE_SG || mac_proto == PLC_PROTO_TYPE_SPG) {
phy_init_band_filter_gpio();
phy_cfg_band_filter_gpio((uint8_t)band_id);
}
#endif
}
/* phy initialize */
void phy_init(uint32_t mac_proto, uint32_t band_id, plc_tone_mask_id mask_id,
bool_t bbai_en)
{
uint32_t range_id = IOT_PLC_PHY_BAND_RANGE_DFT;
/* check env */
phy_env_pre_check(mac_proto, band_id, mask_id);
/* delay for boot-hang */
os_delay(CHIP_HANG_DELAY);
/* reset phy */
phy_reset(PHY_RST_REASON_COLD);
/* enable phy reg clk */
phy_eb(true);
/* update phy band */
phy_band_info_update(mac_proto, range_id, band_id, mask_id);
/* load pib cfg*/
#if HW_PLATFORM >= HW_PLATFORM_FPGA
phy_load_pib_cfg();
#endif
#if HW_PLATFORM == HW_PLATFORM_FPGA
/* ana init */
phy_ana_init(band_id);
#elif HW_PLATFORM == HW_PLATFORM_SILICON
/* calibration form pib */
phy_load_cal_cfg();
/* CPU switch to 25M */
clk_core_freq_slip_25m_set();
/* analog initial */
phy_ana_init(band_id);
/* gpio mapping */
geode_gpio_init();
#if IOT_DTEST_ONLY_SUPPORT == 0
/* phy low power start */
phy_pm_start();
#endif
/* CPU switch to 150M */
clk_core_freq_slip_150m_set();
#endif
/* map plc protocol phase to hw phase */
phy_set_phase_overwrite(true,
HW_DESC_PHASE_ALL,
HW_DESC_PHASE_A,
HW_DESC_PHASE_B,
HW_DESC_PHASE_C);
/* config software version to register */
PHY_DFE_WRITE_REG(CFG_BB_DFE_SPARE2_ADDR,PHY_SW_VER);
/* init phy register */
phy_param_init(PHY_PROTO_TYPE_GET());
/* delay for boot-hang */
os_delay(CHIP_HANG_DELAY);
#if IOT_DTEST_ONLY_SUPPORT == 0
if (phy_get_fw_mode() != MP_MODE) {
/* WAR:bugid 244, enable phy isr for sack tx */
if (PHY_PROTO_TYPE_GET() != PLC_PROTO_TYPE_GP) {
phy_isr_init();
phy_isr_start();
phy_isr_start_cpu1();
}
}
/* update fl for mac */
phy_symppb_flppb_init(mac_proto);
/* sts cnt log */
register_regular_log(phy_get_status_printf);
/* delay for boot-hang */
os_delay(CHIP_HANG_DELAY);
/* channel pre-estimate */
/*high_perf_en is 0 when first power on*/
if (bbai_en == true) {
g_phy_cpu_share_ctxt.high_perf_en = 0;
phy_chn_est_pre_detect();
}
#if HW_PLATFORM >= HW_PLATFORM_FPGA
/* init timer */
phy_nf_timer_start();
#endif
#endif
#if HW_PLATFORM >= HW_PLATFORM_FPGA
if (range_id == IOT_SUPPORT_PROTO_SG_NSG_BAND) {
/* support diff featue base on platform */
phy_spcl_feat_init();
}
#endif
/*record phy init cnt*/
phy_set_init_cnt();
/* init multiband special optimization */
if (band_id == IOT_SUPPORT_TONE_MULTI_BAND021) {
phy_multi_band_opt_ena(band_id);
}
/* war for bug
* sometime cco start, failure to receive package.
* add phy_reset to work around.
*/
phy_reset(PHY_RST_REASON_WARM);
/* init phy temperature */
phy_temperature_adc_init();
#if PHY_HW_SPIKE_OPTIMIZATION
if (IOT_SUPPORT_TONE_32_120 == band_id) {
phy_rxfd_pkt_det_thd_set(8, 16);
}
#endif
/* delay for boot-hang */
os_delay(CHIP_HANG_DELAY);
return;
}
/* phy re-init */
void phy_reinit(uint32_t mac_proto, uint32_t band_id, plc_tone_mask_id mask_id,
bool_t bbai_en)
{
uint32_t range_id = IOT_PLC_PHY_BAND_RANGE_DFT;
/* check env */
phy_env_pre_check(mac_proto, band_id, mask_id);
/* TODO: check if need disable clock */
/* reset phy */
phy_reset(PHY_RST_REASON_WARM);
/* update phy band */
phy_band_info_update(mac_proto, range_id, band_id, mask_id);
/* load pib cfg*/
#if HW_PLATFORM >= HW_PLATFORM_FPGA
phy_load_pib_cfg();
#endif
#if HW_PLATFORM == HW_PLATFORM_SILICON
/* calibration from pib */
phy_load_cal_cfg();
phy_ana_init(band_id);
#endif
/* init phy register */
phy_param_init(mac_proto);
#if IOT_DTEST_ONLY_SUPPORT == 0
phy_symppb_flppb_init(mac_proto);
if (bbai_en == true) {
/* channel pre-estimate */
phy_chn_est_pre_detect();
}
#endif
#if HW_PLATFORM >= HW_PLATFORM_FPGA
if (range_id == IOT_SUPPORT_PROTO_SG_NSG_BAND) {
/* support diff featue base on platform */
phy_spcl_feat_init();
}
#endif
/*record phy reinit cnt*/
phy_set_reinit_cnt();
#if PHY_HW_SPIKE_OPTIMIZATION
if (IOT_SUPPORT_TONE_32_120 == band_id) {
phy_rxfd_pkt_det_thd_set(8, 16);
}
#endif
return;
}
void phy_new_cfg_apply()
{
/* apply new phy mode */
phy_reinit(g_phy_ctxt.indep.chn.phy_proto_tobe,
g_phy_ctxt.indep.chn.band_id_tobe,
g_phy_ctxt.indep.chn.mask_id_tobe,
true);
/* clr fc ok find flag */
#if IOT_DTEST_ONLY_SUPPORT == 0
g_phy_cpu_share_ctxt.pm_status.fc_ok_found = 0;
#endif
}
void phy_trx_phase_switch_gpio_init()
{
uint8_t txrx_switch_a = iot_board_get_gpio(GPIO_TXRX_SWITCH_A);
uint8_t txrx_switch_b = iot_board_get_gpio(GPIO_TXRX_SWITCH_B);
uint8_t txrx_switch_c = iot_board_get_gpio(GPIO_TXRX_SWITCH_C);
if (txrx_switch_a == GPIO_NO_VALID || txrx_switch_b == GPIO_NO_VALID ||
txrx_switch_c == GPIO_NO_VALID) {
g_phy_cpu_share_ctxt.trx_phase_switch_en = 0;
iot_printf("%s not_support trx switch gpio phase config\n",
__FUNCTION__);
return;
}
g_phy_cpu_share_ctxt.trx_phase_switch_en = 1;
g_phy_cpu_share_ctxt.trx_switch_phase = PLC_PHASE_A;
/* default enable phase a */
iot_gpio_open_as_output(txrx_switch_a);
iot_gpio_value_set(txrx_switch_a, 1);
iot_gpio_open_as_output(txrx_switch_b);
iot_gpio_value_set(txrx_switch_b, 0);
iot_gpio_open_as_output(txrx_switch_c);
iot_gpio_value_set(txrx_switch_c, 0);
}
uint32_t phy_set_trx_switch_gpio_phase(uint8_t phase)
{
if (!g_phy_cpu_share_ctxt.trx_phase_switch_en) {
return ERR_FAIL;
}
if (phase > PLC_PHASE_CNT) {
return ERR_FAIL;
}
g_phy_cpu_share_ctxt.trx_switch_phase = phase;
uint8_t txrx_switch_a = iot_board_get_gpio(GPIO_TXRX_SWITCH_A);
uint8_t txrx_switch_b = iot_board_get_gpio(GPIO_TXRX_SWITCH_B);
uint8_t txrx_switch_c = iot_board_get_gpio(GPIO_TXRX_SWITCH_C);
if (PLC_PHASE_A == phase) {
/* phase A */
iot_gpio_value_set(txrx_switch_a, 1);
iot_gpio_value_set(txrx_switch_b, 0);
iot_gpio_value_set(txrx_switch_c, 0);
} else if (PLC_PHASE_B == phase) {
/* phase B */
iot_gpio_value_set(txrx_switch_a, 0);
iot_gpio_value_set(txrx_switch_b, 1);
iot_gpio_value_set(txrx_switch_c, 0);
} else if (PLC_PHASE_C == phase) {
/* phase C */
iot_gpio_value_set(txrx_switch_a, 0);
iot_gpio_value_set(txrx_switch_b, 0);
iot_gpio_value_set(txrx_switch_c, 1);
} else {
/* phase ALL */
iot_gpio_value_set(txrx_switch_a, 1);
iot_gpio_value_set(txrx_switch_b, 1);
iot_gpio_value_set(txrx_switch_c, 1);
}
return ERR_OK;
}
uint8_t phy_get_trx_switch_gpio_phase()
{
if (!g_phy_cpu_share_ctxt.trx_phase_switch_en) {
return PLC_PHASE_A;
}
return (uint8_t)g_phy_cpu_share_ctxt.trx_switch_phase;
}