426 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			426 lines
		
	
	
		
			11 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 "chip_reg_base.h"
 | 
						|
#include "hw_reg_api.h"
 | 
						|
#include "plc_fr.h"
 | 
						|
#include "mac_reset.h"
 | 
						|
#include "mac_sys_reg.h"
 | 
						|
#include "ahb.h"
 | 
						|
#include "hw_desc.h"
 | 
						|
#include "hw_phy_init.h"
 | 
						|
#include "mac_raw_reg.h"
 | 
						|
#include "mac_init_api.h"
 | 
						|
/* HW WAR for cfg reg not take effect */
 | 
						|
#include "mac_txq_hw.h"
 | 
						|
#include "mac_status.h"
 | 
						|
#include "mac_sched_hw.h"
 | 
						|
#include "tx_mpdu_start.h"
 | 
						|
#include "os_utils_api.h"
 | 
						|
#include "phy_reg.h"
 | 
						|
#include "mac_pdev.h"
 | 
						|
#include "iot_system_api.h"
 | 
						|
#include "os_task.h"
 | 
						|
#include "phy_phase.h"
 | 
						|
 | 
						|
void enable_mac(uint32_t enable) {
 | 
						|
#if HW_PLATFORM != HW_PLATFORM_SIMU
 | 
						|
    if (enable) {
 | 
						|
        ahb_mac_enable();
 | 
						|
    } else {
 | 
						|
        ahb_mac_disable();
 | 
						|
    }
 | 
						|
#else
 | 
						|
    (void)enable;
 | 
						|
#endif
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void warm_rst_mac_hold() {
 | 
						|
#if HW_PLATFORM != HW_PLATFORM_SIMU
 | 
						|
    ahb_mac_reset_hold();
 | 
						|
#endif
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void warm_rst_mac_release() {
 | 
						|
#if HW_PLATFORM != HW_PLATFORM_SIMU
 | 
						|
    ahb_mac_reset_release();
 | 
						|
#endif
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void mac_cfg_reg_reset()
 | 
						|
{
 | 
						|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
 | 
						|
    ahb_mac_reset();
 | 
						|
 | 
						|
    /* Sadc stop working after phy reset, but dma still working, dma will move
 | 
						|
     * error data to buffer. So, we need reset sadc after phy reset quickly.
 | 
						|
     * See details at bugID:733.
 | 
						|
     * 1:select the sadc data; 0:select adc 16-downsampling data.
 | 
						|
     */
 | 
						|
    phy_adc_mon_sel_set(true);
 | 
						|
#endif
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void mac_reset(MAC_RST_REASON_ID rst_reason) {
 | 
						|
    (void)rst_reason;
 | 
						|
    enable_mac(true);
 | 
						|
 | 
						|
    warm_rst_mac_hold();
 | 
						|
    warm_rst_mac_release();
 | 
						|
 | 
						|
    /* not reset all reg here, as the cfg reg reset
 | 
						|
     * not only reset mac reg, put it at phy_reset()
 | 
						|
     */
 | 
						|
}
 | 
						|
 | 
						|
void mac_warm_reset_war(uint32_t flag) {
 | 
						|
    (void)flag;
 | 
						|
 | 
						|
    if (flag == CONT_RX_ABORT4) {
 | 
						|
#if ENA_WAR_244
 | 
						|
        /* disable MAC RAW DATA MODE */
 | 
						|
        RGF_RAW_WRITE_REG(CFG_RAW_DATA_MODE_ADDR, 0);
 | 
						|
        /* clear pb size BB */
 | 
						|
        phy_rawdata_mode_bb_set_ps_tr(0,0,0);
 | 
						|
#endif
 | 
						|
    } else if (flag == PHY_TX_HANG){
 | 
						|
        mac_new_phy_cfg_apply();
 | 
						|
 | 
						|
        /* clear mac status cnt */
 | 
						|
        mac_status_cnt_clr();
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void mac_set_sw_idle_mode(uint32_t ena, uint32_t is_idle) {
 | 
						|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
 | 
						|
    uint32_t tmp;
 | 
						|
    tmp = RGF_MAC_READ_REG(CFG_PHASE_BAND_SEL_ADDR);
 | 
						|
    REG_FIELD_SET(CFG_SW_IDLE_MODE_EN, tmp, ena);
 | 
						|
    REG_FIELD_SET(CFG_SW_IDLE_MODE, tmp, is_idle);
 | 
						|
    RGF_MAC_WRITE_REG(CFG_PHASE_BAND_SEL_ADDR, tmp);
 | 
						|
#else
 | 
						|
    (void)ena;
 | 
						|
    (void)is_idle;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
uint32_t mac_wait_phy_txrx_idle() {
 | 
						|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
 | 
						|
    /* return 0 for wait idle successful
 | 
						|
     * 1 for wait failed if timeout
 | 
						|
     */
 | 
						|
    /* TODO: support timeout */
 | 
						|
    uint32_t tmp;
 | 
						|
    uint32_t tx_active;
 | 
						|
    uint32_t rx_active;
 | 
						|
    do {
 | 
						|
        tmp = RGF_MAC_READ_REG(CFG_RD_MACPHY_INTF_0_ADDR);
 | 
						|
        rx_active = REG_FIELD_GET(PHY_RX_ENABLE, tmp);
 | 
						|
        tx_active = REG_FIELD_GET(PHY_TX_ENABLE, tmp);
 | 
						|
    } while (tx_active && rx_active);
 | 
						|
#else
 | 
						|
#endif
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
void mac_force_phy_tx_ready(uint32_t ena, uint32_t is_force_ready) {
 | 
						|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
 | 
						|
    /* make phy tx ready to 1 before mac disable hwq */
 | 
						|
    uint32_t tmp;
 | 
						|
    tmp = RGF_MAC_READ_REG(CFG_PHY_FORCE_2_ADDR);
 | 
						|
    REG_FIELD_SET(CFG_PHY_TX_READY_FORCE_EN, tmp, ena);
 | 
						|
    REG_FIELD_SET(CFG_PHY_TX_READY, tmp, is_force_ready);
 | 
						|
    RGF_MAC_WRITE_REG(CFG_PHY_FORCE_2_ADDR, tmp);
 | 
						|
#else
 | 
						|
    (void)ena;
 | 
						|
    (void)is_force_ready;
 | 
						|
#endif
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t mac_dbg_bus_is_in_tx()
 | 
						|
{
 | 
						|
#define TX_FSM_IS_TX_MASK    0x38000
 | 
						|
    uint32_t debug_tmp;
 | 
						|
    mac_set_debug_reg(0x100);
 | 
						|
    debug_tmp = mac_rx_get_debug_reg();
 | 
						|
    /* if 0, then means idle */
 | 
						|
    return debug_tmp & TX_FSM_IS_TX_MASK;
 | 
						|
}
 | 
						|
 | 
						|
void mac_tx_wait_all_queue_idle(uint32_t iscco, uint32_t time_ms)
 | 
						|
{
 | 
						|
    uint32_t start_ts = os_boot_time32();
 | 
						|
#if DEBUG_HWQ_SHCED_HANG
 | 
						|
    uint32_t try_cnt = 0;
 | 
						|
#endif
 | 
						|
    while (mac_dbg_bus_is_in_tx()) {
 | 
						|
        if (os_boot_time32() - start_ts > time_ms) {
 | 
						|
#if DEBUG_HWQ_SHCED_HANG
 | 
						|
            try_cnt++;
 | 
						|
            /* war for stop sched hang */
 | 
						|
            if (try_cnt < 2) {
 | 
						|
                /* force mac phy interface */
 | 
						|
                mac_force_mac_phy_interface(1);
 | 
						|
                os_delay(1);
 | 
						|
                mac_force_mac_phy_interface(0);
 | 
						|
            } else
 | 
						|
#endif
 | 
						|
            {
 | 
						|
#if WAR_HWQ_SHCED_HANG
 | 
						|
                /* reset chip */
 | 
						|
                iot_system_restart(IOT_SYS_RST_REASON_MAC_TX_HANG);
 | 
						|
#endif
 | 
						|
                /* if try_cnt >= 2 then assert */
 | 
						|
                mac_dump_buf(MAC_DUMP_TYPE_4,
 | 
						|
                        (uint32_t *)mac_txq_get_curr_desc_ptr(\
 | 
						|
                        !!iscco, \
 | 
						|
                        false), \
 | 
						|
                        sizeof(tx_mpdu_start)/sizeof(uint32_t), \
 | 
						|
                        (uint32_t *)RGF_HWQ_BASEADDR, 108, \
 | 
						|
                        (uint32_t *)(PHY_BASEADDR + CFG_BB_RX_TD_DBG_BUS0_ADDR),
 | 
						|
                        38, true);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void mac_sw_trig_need_en(bool_t ena)
 | 
						|
{
 | 
						|
    /* for kunlun 1 we don't have this define */
 | 
						|
    (void)ena;
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void mac_sw_trig_start(bool_t ena)
 | 
						|
{
 | 
						|
    /* for kunlun 1 we don't have this define */
 | 
						|
 | 
						|
    (void)ena;
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void mac_dma_ckl_sel(bool_t ena)
 | 
						|
 {
 | 
						|
     /* for kunlun 1 we don't have this define */
 | 
						|
 | 
						|
     (void)ena;
 | 
						|
     return;
 | 
						|
 }
 | 
						|
 | 
						|
uint32_t mac_get_phy_txrx_sts()
 | 
						|
{
 | 
						|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
 | 
						|
     uint32_t tmp;
 | 
						|
     uint32_t tx_active;
 | 
						|
     uint32_t rx_active;
 | 
						|
     tmp = RGF_MAC_READ_REG(CFG_RD_MACPHY_INTF_0_ADDR);
 | 
						|
     rx_active = REG_FIELD_GET(PHY_RX_ENABLE, tmp);
 | 
						|
     tx_active = REG_FIELD_GET(PHY_TX_ENABLE, tmp);
 | 
						|
     if (rx_active == 0 && tx_active == 0) {
 | 
						|
         return MAC_PHY_IDLE_STS;
 | 
						|
     }
 | 
						|
     else if (rx_active == 1 && tx_active == 0) {
 | 
						|
         return MAC_PHY_RX_STS;
 | 
						|
     }
 | 
						|
     else if (rx_active == 0 && tx_active == 1) {
 | 
						|
         return MAC_PHY_TX_STS;
 | 
						|
     }
 | 
						|
     else if (rx_active == 1 && tx_active == 1) {
 | 
						|
         IOT_ASSERT(0);
 | 
						|
         return MAC_PHY_UNKNOW_STS;
 | 
						|
     }
 | 
						|
#else
 | 
						|
#endif
 | 
						|
     return 0;
 | 
						|
}
 | 
						|
 | 
						|
/* NOTE: this function cannot call in interrupt */
 | 
						|
uint32_t mac_set_sts_idle()
 | 
						|
{
 | 
						|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
 | 
						|
 | 
						|
    uint32_t tmp;
 | 
						|
 | 
						|
    phy_force_0_access_require();
 | 
						|
 | 
						|
    tmp = RGF_MAC_READ_REG(CFG_PHY_FORCE_0_ADDR);
 | 
						|
 | 
						|
    REG_FIELD_SET(CFG_PHY_RX_FRAME_FORCE_EN, tmp, 1);
 | 
						|
    REG_FIELD_SET(CFG_PHY_RX_FRAME, tmp, 0);
 | 
						|
 | 
						|
    REG_FIELD_SET(CFG_PHY_RX_VLD_FORCE_EN, tmp, 1);
 | 
						|
    REG_FIELD_SET(CFG_PHY_RX_VLD, tmp, 0);
 | 
						|
 | 
						|
    REG_FIELD_SET(CFG_PHY_FC_CRC_DONE_FORCE_EN, tmp, 1);
 | 
						|
    REG_FIELD_SET(CFG_PHY_FC_CRC_DONE, tmp, 0);
 | 
						|
 | 
						|
    REG_FIELD_SET(CFG_PHY_PB_CRC_DONE_FORCE_EN, tmp, 1);
 | 
						|
    REG_FIELD_SET(CFG_PHY_PB_CRC_DONE, tmp, 0);
 | 
						|
 | 
						|
    RGF_MAC_WRITE_REG(CFG_PHY_FORCE_0_ADDR, tmp);
 | 
						|
 | 
						|
    phy_force_0_access_release();
 | 
						|
 | 
						|
    tmp = RGF_MAC_READ_REG(CFG_PHY_FORCE_1_ADDR);
 | 
						|
 | 
						|
    REG_FIELD_SET(CFG_PHY_PB_RCV_DONE_FORCE_EN, tmp, 1);
 | 
						|
    REG_FIELD_SET(CFG_PHY_PB_RCV_DONE, tmp, 0);
 | 
						|
 | 
						|
    REG_FIELD_SET(CFG_PHY_FC_RCV_DONE_FORCE_EN, tmp, 1);
 | 
						|
    REG_FIELD_SET(CFG_PHY_FC_RCV_DONE, tmp, 0);
 | 
						|
 | 
						|
    RGF_MAC_WRITE_REG(CFG_PHY_FORCE_1_ADDR, tmp);
 | 
						|
 | 
						|
    tmp = RGF_MAC_READ_REG(CFG_PHY_FORCE_2_ADDR);
 | 
						|
    REG_FIELD_SET(CFG_PHY_TX_READY_FORCE_EN, tmp, 1);
 | 
						|
    REG_FIELD_SET(CFG_PHY_TX_READY, tmp, 1);
 | 
						|
    RGF_MAC_WRITE_REG(CFG_PHY_FORCE_2_ADDR, tmp);
 | 
						|
 | 
						|
#else
 | 
						|
#endif
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
/* NOTE: this function cannot call in interrupt */
 | 
						|
uint32_t mac_free_sts_idle()
 | 
						|
{
 | 
						|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
 | 
						|
 | 
						|
    uint32_t tmp;
 | 
						|
 | 
						|
    phy_force_0_access_require();
 | 
						|
 | 
						|
    tmp = RGF_MAC_READ_REG(CFG_PHY_FORCE_0_ADDR);
 | 
						|
 | 
						|
    REG_FIELD_SET(CFG_PHY_RX_FRAME_FORCE_EN, tmp, 0);
 | 
						|
    REG_FIELD_SET(CFG_PHY_RX_FRAME, tmp, 0);
 | 
						|
 | 
						|
    REG_FIELD_SET(CFG_PHY_RX_VLD_FORCE_EN, tmp, 0);
 | 
						|
    REG_FIELD_SET(CFG_PHY_RX_VLD, tmp, 0);
 | 
						|
 | 
						|
    REG_FIELD_SET(CFG_PHY_FC_CRC_DONE_FORCE_EN, tmp, 0);
 | 
						|
    REG_FIELD_SET(CFG_PHY_FC_CRC_DONE, tmp, 0);
 | 
						|
 | 
						|
    REG_FIELD_SET(CFG_PHY_PB_CRC_DONE_FORCE_EN, tmp, 0);
 | 
						|
    REG_FIELD_SET(CFG_PHY_PB_CRC_DONE, tmp, 0);
 | 
						|
 | 
						|
    RGF_MAC_WRITE_REG(CFG_PHY_FORCE_0_ADDR, tmp);
 | 
						|
 | 
						|
    phy_force_0_access_release();
 | 
						|
 | 
						|
    tmp = RGF_MAC_READ_REG(CFG_PHY_FORCE_1_ADDR);
 | 
						|
 | 
						|
    REG_FIELD_SET(CFG_PHY_PB_RCV_DONE_FORCE_EN, tmp, 0);
 | 
						|
    REG_FIELD_SET(CFG_PHY_PB_RCV_DONE, tmp, 0);
 | 
						|
 | 
						|
    REG_FIELD_SET(CFG_PHY_FC_RCV_DONE_FORCE_EN, tmp, 0);
 | 
						|
    REG_FIELD_SET(CFG_PHY_FC_RCV_DONE, tmp, 0);
 | 
						|
 | 
						|
    RGF_MAC_WRITE_REG(CFG_PHY_FORCE_1_ADDR, tmp);
 | 
						|
 | 
						|
    tmp = RGF_MAC_READ_REG(CFG_PHY_FORCE_2_ADDR);
 | 
						|
 | 
						|
    REG_FIELD_SET(CFG_PHY_TX_READY_FORCE_EN, tmp, 0);
 | 
						|
    REG_FIELD_SET(CFG_PHY_TX_READY, tmp, 0);
 | 
						|
 | 
						|
    RGF_MAC_WRITE_REG(CFG_PHY_FORCE_2_ADDR, tmp);
 | 
						|
#else
 | 
						|
#endif
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t mac_dbg_bus_get_mac_sts(uint32_t value, uint32_t mask)
 | 
						|
{
 | 
						|
    uint32_t debug_tmp;
 | 
						|
    mac_set_debug_reg(value);
 | 
						|
    debug_tmp = mac_rx_get_debug_reg();
 | 
						|
    /* if 0, then means idle */
 | 
						|
    return debug_tmp & mask;
 | 
						|
}
 | 
						|
 | 
						|
/* NOTE: this function cannot call in interrupt */
 | 
						|
uint32_t mac_set_pcs_busy(uint32_t enable, uint32_t value)
 | 
						|
{
 | 
						|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
 | 
						|
    uint32_t tmp;
 | 
						|
    phy_force_0_access_require();
 | 
						|
    tmp = RGF_MAC_READ_REG(CFG_PHY_FORCE_0_ADDR);
 | 
						|
    REG_FIELD_SET(CFG_PHY_PCS_BUSY_FORCE_EN, tmp, enable);
 | 
						|
    REG_FIELD_SET(CFG_PHY_PCS_BUSY, tmp, value);
 | 
						|
    RGF_MAC_WRITE_REG(CFG_PHY_FORCE_0_ADDR, tmp);
 | 
						|
    phy_force_0_access_release();
 | 
						|
#else
 | 
						|
    (void)enable;
 | 
						|
    (void)value;
 | 
						|
#endif
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
/* NOTE: this function cannot call in interrupt */
 | 
						|
uint32_t mac_set_fc_crc_done(uint32_t enable, uint32_t value)
 | 
						|
{
 | 
						|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
 | 
						|
    uint32_t tmp;
 | 
						|
    phy_force_0_access_require();
 | 
						|
    tmp = RGF_MAC_READ_REG(CFG_PHY_FORCE_0_ADDR);
 | 
						|
    REG_FIELD_SET(CFG_PHY_FC_CRC_DONE_FORCE_EN, tmp, enable);
 | 
						|
    REG_FIELD_SET(CFG_PHY_FC_CRC_DONE, tmp, value);
 | 
						|
    RGF_MAC_WRITE_REG(CFG_PHY_FORCE_0_ADDR, tmp);
 | 
						|
    phy_force_0_access_release();
 | 
						|
#else
 | 
						|
    (void)enable;
 | 
						|
    (void)value;
 | 
						|
#endif
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t mac_set_reg_tx_abort_debug_value()
 | 
						|
{
 | 
						|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
 | 
						|
    uint32_t tmp;
 | 
						|
    tmp = RGF_MAC_READ_REG(CFG_PHY_FORCE_1_ADDR);
 | 
						|
    REG_FIELD_SET(CFG_PHY_TX_ABORT_FORCE_EN, tmp, 1);
 | 
						|
    REG_FIELD_SET(CFG_PHY_TX_ABORT, tmp, 0);
 | 
						|
    RGF_MAC_WRITE_REG(CFG_PHY_FORCE_1_ADDR, tmp);
 | 
						|
#endif
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t mac_force_mac_phy_interface(uint32_t value)
 | 
						|
{
 | 
						|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
 | 
						|
    uint32_t tmp;
 | 
						|
    tmp = RGF_MAC_READ_REG(CFG_PHY_FORCE_2_ADDR);
 | 
						|
 | 
						|
    REG_FIELD_SET(CFG_PHY_TX_READY_FORCE_EN, tmp, value);
 | 
						|
    REG_FIELD_SET(CFG_PHY_TX_READY, tmp, value);
 | 
						|
 | 
						|
    REG_FIELD_SET(CFG_PHY_TX_PROCESSING_FORCE_EN, tmp, value);
 | 
						|
    REG_FIELD_SET(CFG_PHY_TX_PROCESSING, tmp, value);
 | 
						|
 | 
						|
    RGF_MAC_WRITE_REG(CFG_PHY_FORCE_2_ADDR, tmp);
 | 
						|
#else
 | 
						|
    (void)value;
 | 
						|
#endif
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 |