426 lines
11 KiB
C
426 lines
11 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 "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;
|
||
|
}
|
||
|
|