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