348 lines
8.8 KiB
C
Executable File
348 lines
8.8 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 "iot_config.h"
|
|
#include "mac_init_api.h"
|
|
#include "clk.h"
|
|
|
|
/* for test only */
|
|
#include "beacon_frame.h"
|
|
#include "mac_vdev.h"
|
|
#include "mac_vdev_api.h"
|
|
#include "mac_pdev.h"
|
|
#include "mac_rx_hw.h"
|
|
#include "mac_tx_hw.h"
|
|
#include "mac_data.h"
|
|
#include "mac_reset.h"
|
|
#include "mac_desc_engine.h"
|
|
#include "mac_task.h"
|
|
#include "mac_msg.h"
|
|
#include "mac_dsr.h"
|
|
#include "mac_isr.h"
|
|
#include "phy_bb.h"
|
|
|
|
/* common includes */
|
|
#include "iot_mem_pool.h"
|
|
#include "iot_errno.h"
|
|
#include "iot_io.h"
|
|
#include "iot_system.h"
|
|
|
|
#include "sw_sched.h"
|
|
#include "mac_cert_test.h"
|
|
|
|
#include "hw_phy_init.h"
|
|
#include "phy_phase.h"
|
|
#include "mac_cfg.h"
|
|
#include "mac_zc.h"
|
|
#include "iot_cli.h"
|
|
#include "mac_status.h"
|
|
|
|
#include "iot_plc_pm_api.h"
|
|
#include "mac_pm.h"
|
|
#include "mac_sched.h"
|
|
#include "mac_sched_hw.h"
|
|
#include "mac_tx_power.h"
|
|
#include "phy_txrx_pwr.h"
|
|
#include "mac_check_spur.h"
|
|
#include "mac_cert_test.h"
|
|
#include "phy_nf.h"
|
|
#include "mac_rf_sched.h"
|
|
#include "phy_rf_init.h"
|
|
#include "phy_rf_chn.h"
|
|
#include "mac_rf_tx_hw.h"
|
|
#include "mac_cmn_hw.h"
|
|
#if HPLC_RF_DEV_SUPPORT
|
|
#include "mac_rf_isr.h"
|
|
#endif
|
|
|
|
/* mac layer global data */
|
|
mac_global_t* p_mac_glb = NULL;
|
|
|
|
/*
|
|
* mac_init - initialize mac modules
|
|
*
|
|
* return 0 for success and non-zero for failure.
|
|
*
|
|
*/
|
|
uint32_t mac_init(uint32_t proto)
|
|
{
|
|
uint32_t ret = 0;
|
|
|
|
iot_printf("%s, proto:%d-%d\n", __FUNCTION__, proto, SUPPORT_IEEE_1901);
|
|
|
|
/* hw init */
|
|
mac_reset(MAC_RST_REASON_COLD);
|
|
|
|
/* hw auto fix 32bit ntb wrap, support begins kunlun3 */
|
|
mac_ena_hw_ntb_wrap_fix(1);
|
|
|
|
if (ENA_HIGH32_EQUAL_ONE) {
|
|
/* war for high 32bit ntb overflow down */
|
|
mac_sched_sync_ntb(NULL, 0, 0x7fffffff);
|
|
mac_sched_sync_ntb(NULL, 0, 0x7fffffff);
|
|
}
|
|
|
|
/* mac config info init */
|
|
mac_cfg_init();
|
|
|
|
p_mac_glb = os_mem_malloc(PLC_MAC_COMMON_MID, sizeof(*p_mac_glb));
|
|
if (p_mac_glb == NULL) {
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
|
|
mac_isr_init(mac_dsr_set_from_isr);
|
|
|
|
mac_dsr_init(&p_mac_glb->dsr_table);
|
|
|
|
ret = mac_desc_engine_init(&g_mac_desc_eng, NULL);
|
|
if (ret)
|
|
goto err_desc;
|
|
|
|
ret = mac_pdev_init();
|
|
if (ret)
|
|
goto err_pdev;
|
|
|
|
mac_swsch_init();
|
|
|
|
mac_rf_swsch_init();
|
|
|
|
mac_cert_test_g_init();
|
|
|
|
mac_token_bucket_init();
|
|
|
|
register_regular_log(mac_get_status_printf);
|
|
|
|
register_get_rx_phase_cb(mac_get_sche_rx_phase);
|
|
|
|
register_over_stress_cb(mac_over_stress_isr_handle);
|
|
|
|
iot_plc_pm_register_listener(mac_pm_rx_power_off);
|
|
|
|
register_phy_call_mac_bbai_cb(mac_phy_channel_est_msg);
|
|
|
|
register_phy_get_cert_mode_cb(mac_get_cert_test_mode);
|
|
|
|
register_phy_call_mac_dsr_cb(mac_dsr_set_phy_timer);
|
|
|
|
ret = mac_init_msg_pool();
|
|
if (ret)
|
|
goto err_msg;
|
|
|
|
ret = mac_start_task(p_mac_glb);
|
|
if (ret)
|
|
goto err_task;
|
|
|
|
mac_zc_system_init(MAC_ZC_DEFAULT_ID,
|
|
(void *)p_mac_glb->task_h,
|
|
(void *)&p_mac_glb->dsr_table,
|
|
(void *)mac_dsr_set_entry, (void *)mac_dsr_clear);
|
|
|
|
/* start mac interrupt service */
|
|
mac_isr_start();
|
|
|
|
/* start rf isr */
|
|
#if HPLC_RF_DEV_SUPPORT
|
|
mac_rf_isr_start();
|
|
#endif
|
|
|
|
goto out;
|
|
|
|
err_task:
|
|
mac_deinit_msg_pool();
|
|
err_msg:
|
|
/* TBD. add msg init error handling */
|
|
err_pdev:
|
|
/* TBD. add pdev init error handling */
|
|
err_desc:
|
|
/* TBD. add desc init error handling */
|
|
os_mem_free(p_mac_glb);
|
|
p_mac_glb = NULL;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
/*reset mac and phy*/
|
|
uint32_t mac_reinit(uint32_t reason, uint32_t proto, uint32_t bandid,
|
|
uint32_t tonemask_id, uint32_t rf_option, uint8_t rf_channel)
|
|
{
|
|
/* pm init wake up */
|
|
mac_pm_init_wake_up();
|
|
/* register rst */
|
|
mac_cfg_reg_reset();
|
|
|
|
/* pre reinit */
|
|
mac_set_sw_idle_mode(1, 1);
|
|
mac_wait_phy_txrx_idle();
|
|
mac_force_phy_tx_ready(1, 1);
|
|
|
|
/* init rf power */
|
|
phy_rf_set_init_power();
|
|
/* record dbg cnt */
|
|
phy_record_dbg_cnt();
|
|
|
|
uint32_t sync_init = 0;
|
|
/* rf phy init, plc cpu and bbcpu async init, rf rxdc enable */
|
|
phy_rf_init(proto, rf_option, rf_channel, sync_init, 1, 1);
|
|
|
|
/* phy init */
|
|
phy_init(proto, bandid, tonemask_id, true);
|
|
|
|
/* wait bbcpu init complete */
|
|
if (!sync_init) {
|
|
phy_rf_wait_init();
|
|
}
|
|
|
|
/* recover dbg cnt */
|
|
phy_recover_dbg_cnt();
|
|
|
|
/* release idle mode */
|
|
mac_force_phy_tx_ready(0, 0);
|
|
/* must del ena after del force */
|
|
mac_set_sw_idle_mode(1,0);
|
|
mac_set_sw_idle_mode(0,0);
|
|
|
|
/* reset mac */
|
|
mac_reset((PHY_RST_REASON_ID)reason);
|
|
|
|
if (ENA_HIGH32_EQUAL_ONE && MAC_RST_REASON_COLD == reason) {
|
|
mac_sched_sync_ntb(NULL, 0, 0x7fffffff);
|
|
mac_sched_sync_ntb(NULL, 0, 0x7fffffff);
|
|
}
|
|
|
|
/* mac config info init */
|
|
mac_cfg_init();
|
|
|
|
/*mac isr init*/
|
|
mac_isr_init(mac_dsr_set_from_isr);
|
|
|
|
/*mac pdev init*/
|
|
mac_pdev_init();
|
|
|
|
/* start mac interrupt service */
|
|
mac_isr_start();
|
|
|
|
/* start rf isr */
|
|
#if HPLC_RF_DEV_SUPPORT
|
|
mac_rf_isr_start();
|
|
#endif
|
|
|
|
/* TODO: if WAR_SPUR_CHECK_MAC_RESET support, need restart mac zc */
|
|
|
|
/* clear mac status cnt */
|
|
mac_status_cnt_clr();
|
|
|
|
/* info pm module that we can sleep now */
|
|
req_stay_awake(MAC_PM_INIT_MODULE_ID, false);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void mac_pre_phy_reinit() {
|
|
mac_rf_pdev_t *rf_pdev = NULL;
|
|
mac_rf_vdev_t *rf_vdev = NULL;
|
|
mac_pdev_t *pdev = g_mac_pdev[PLC_PDEV_ID];
|
|
mac_vdev_t *vdev = get_vdev_ptr(PLC_PDEV_ID, PLC_DEFAULT_VDEV);
|
|
|
|
if (vdev == NULL)
|
|
return;
|
|
rf_pdev = get_rf_pdev_ptr(PLC_PDEV_ID, RF_PDEV_ID);
|
|
if (rf_pdev) {
|
|
rf_vdev = get_rf_vdev_ptr(vdev->ref_pdev_id, rf_pdev->rf_pdev_id,
|
|
vdev->rf_vdev_id);
|
|
}
|
|
|
|
/* stop current HW scheduler */
|
|
mac_sched_stop(vdev);
|
|
|
|
/* rf schedule stop */
|
|
mac_rf_sched_stop(rf_vdev);
|
|
|
|
/* pm init wake up */
|
|
mac_pm_init_wake_up();
|
|
|
|
/* wait hwq to be idle */
|
|
/* max gap between backoff and tx start */
|
|
os_delay(1);
|
|
uint32_t iscco = (PLC_DEV_ROLE_CCO == mac_vdev_cfg_get_node_role(vdev));
|
|
mac_tx_wait_all_queue_idle(iscco, MAC_WAIT_TX_IDLE_TIEM_MS);
|
|
|
|
mac_set_sw_idle_mode(1, 1);
|
|
mac_wait_phy_txrx_idle();
|
|
mac_force_phy_tx_ready(1, 1);
|
|
|
|
/* TODO: use a quicker way */
|
|
/* TODO : stop hw tx rx */
|
|
mac_rx_all_ring_disable(pdev);
|
|
/* flush all tdma/csma queue */
|
|
mac_tx_flush_all_queue(&pdev->hwq_hdl, true, true);
|
|
if (rf_pdev) {
|
|
/* flush all tdma/csma queue */
|
|
mac_rf_tx_flush_all_queue(&rf_pdev->hwq_hdl);
|
|
}
|
|
}
|
|
|
|
void mac_post_phy_reinit(uint8_t enable_tx) {
|
|
mac_pdev_t *pdev = g_mac_pdev[PLC_PDEV_ID];
|
|
mac_vdev_t *vdev = get_vdev_ptr(PLC_PDEV_ID, PLC_DEFAULT_VDEV);
|
|
mac_rf_vdev_t *rf_vdev = get_rf_vdev_ptr(vdev->ref_pdev_id,
|
|
RF_PDEV_ID, vdev->rf_vdev_id);
|
|
|
|
/* release idle mode */
|
|
mac_force_phy_tx_ready(0, 0);
|
|
mac_set_sw_idle_mode(1,0);
|
|
mac_set_sw_idle_mode(0,0);
|
|
|
|
if (PLC_DEV_ROLE_CCO != mac_vdev_cfg_get_node_role(vdev)) {
|
|
mac_beacon_ctx_t *bcn_ctx = &vdev->bcn_ctx;
|
|
bcn_ctx->sta.allow_reuse_ts = 0;
|
|
}
|
|
uint64_t start_ntb = mac_sched_get_ntb64(vdev);
|
|
mac_sched_set_csma_only(vdev, start_ntb, enable_tx);
|
|
// TODO: maybe use a function to support rf reset
|
|
/* rf csma only schedule set */
|
|
mac_rf_sched_set_csma_only(rf_vdev, start_ntb, enable_tx);
|
|
|
|
/* enable hw rx */
|
|
mac_rx_all_ring_enable(pdev);
|
|
/* enable tx rx process */
|
|
mac_sw_trig_start(true);
|
|
/* info pm module that we can sleep now */
|
|
req_stay_awake(MAC_PM_INIT_MODULE_ID, false);
|
|
#if CERT_WAR_TX_PWR == 1
|
|
if (vdev->cert_war_pwr) {
|
|
/* recover power if cert war active */
|
|
phy_pwr_adjust_set(PHY_FULL_PWR_DBUV);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void mac_new_phy_cfg_apply()
|
|
{
|
|
#if DEBUG_HWQ_SHCED_HANG
|
|
mac_pdev_t *pdev = g_mac_pdev[PLC_PDEV_ID];
|
|
pdev->dbg_status = MAC_TX_HANG_STATUS_2;
|
|
#endif
|
|
/* do the protection before apply new phy cfg */
|
|
mac_pre_phy_reinit();
|
|
|
|
#if DEBUG_HWQ_SHCED_HANG
|
|
pdev->dbg_status = MACC_TX_HANG_STATUS_MAX;
|
|
#endif
|
|
phy_new_cfg_apply();
|
|
mac_post_phy_reinit(0);
|
|
mac_rx_set_delim(phy_band_id_get(), 0);
|
|
}
|