Files
kunlun/plc/halmac/init/mac_init.c
2024-09-28 14:24:04 +08:00

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);
}