/**************************************************************************** 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 "mac_check_spur.h" #include "mac_check_spur_cco.h" #include "mac_check_spur_sta.h" #include "mac_pdev.h" #include "iot_io.h" #include "mac_msg.h" #include "mac_reset.h" #include "mac_bcm_api.h" #include "mac_vdev.h" #include "iot_utils_api.h" #include "mac_sched.h" #include "mac_tx_hw.h" #include "mac_init_api.h" #include "mac_cert_test.h" #include "os_utils_api.h" #include "mac_sched_hw.h" #include "mac_hwq_reg.h" #include "chip_reg_base.h" #include "hw_reg_api.h" #include "iot_bitmap_api.h" #include "iot_dbglog_api.h" #include "iot_dbglog.h" #if (CCO_CHECK_SPUR_SUPPORT || STA_CHECK_SPUR_SUPPORT) uint32_t mac_check_value(uint32_t value1, uint32_t value2, \ uint32_t value3, uint32_t value4) { uint32_t bit_map = 0; /* 0-7 bit : if valuex == 0, set bitx = 1 */ if (value1 == 0) { bit_map |= 0x1 << 0; } if (value2 == 0) { bit_map |= 0x1 << 1; } if (value3 == 0) { bit_map |= 0x1 << 2; } if (value4 == 0) { bit_map |= 0x1 << 3; } /* 8-15 bit : if valuex == 0, set bitx = 1 */ if (value1 == 2) { bit_map |= 0x1 << 8; } if (value2 == 2) { bit_map |= 0x1 << 9; } if (value3 == 2) { bit_map |= 0x1 << 10; } if (value4 == 2) { bit_map |= 0x1 << 11; } return bit_map; } void mac_print_dbg_bus(uint8_t save_flash) { uint32_t dump_value[] = {0x02, 0x12, 0x22, 0x32, 0x42, 0x50, 0x61, 0x100, 0x200, 0x320, 0x400, 0x401, 0x402, 0x404, 0x405, 0xb00}; for (uint8_t i = 0; i < IOT_ARRAY_CNT(dump_value); i++) { mac_set_debug_reg(dump_value[i]); dump_value[i] = mac_rx_get_debug_reg(); } iot_printf("mac_sts, dbg_reg0 get 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, " "0x%x, 0x%x\n", dump_value[0], dump_value[1], dump_value[2], dump_value[3], dump_value[4], dump_value[5], dump_value[6], dump_value[7]); iot_printf("mac_sts, dbg_reg1 get 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, " "0x%x, 0x%x\n", dump_value[8], dump_value[9], dump_value[10], dump_value[11], dump_value[12], dump_value[13], dump_value[14], dump_value[15]); if (save_flash) { iot_dbglog_input(PLC_MAC_STATUSE_MID, DBGLOG_ERR, IOT_MAC_STATUS14_ID, 8, dump_value[0], dump_value[1], dump_value[2], dump_value[3], dump_value[4], dump_value[5], dump_value[6], dump_value[7]); iot_dbglog_input(PLC_MAC_STATUSE_MID, DBGLOG_ERR, IOT_MAC_STATUS15_ID, 8, dump_value[8], dump_value[9], dump_value[10], dump_value[11], dump_value[12], dump_value[13], dump_value[14], dump_value[15]); } } uint32_t mac_check_spur_en(mac_check_spur_ctxt_t *spur_ctxt, uint32_t enable) { #if (MAC_CHECK_SPUR_DEBUG >= PLC_MAC_LOG_LEVEL_2) iot_printf("%s, [mac_check_dbg], enable:%d\n", __FUNCTION__, enable); #endif if ((mac_get_cert_test_flag() && enable) || spur_ctxt->check_spur_en == (!!enable)) { return 0; } spur_ctxt->check_spur_en = !!enable; if (!enable) { spur_ctxt->is_check_spur_sts = MAC_CHECK_SPUR_INIT; spur_ctxt->con_spur_cnt = 0; spur_ctxt->do_checkspur_cnt = 0; spur_ctxt->do_checkspur_success_cnt = 0; #if CCO_CHECK_SPUR_SUPPORT os_stop_timer(spur_ctxt->cco_check_spur_timer); #else os_stop_timer(spur_ctxt->sta_check_spur_timer); #endif } return 0; } uint32_t mac_check_spur(mac_check_spur_ctxt_t *spur_ctxt, \ void *pdev, uint32_t time_ms, bool_t is_check_slot) { #if (MAC_CHECK_SPUR_DEBUG >= PLC_MAC_LOG_LEVEL_2) iot_printf("%s \n", __FUNCTION__); #endif mac_pdev_t *pdev_t = (mac_pdev_t *)pdev; mac_vdev_t *vdev = pdev_t->vdev[PLC_DEFAULT_VDEV]; uint32_t ret = ERR_FAIL; spur_ctxt->do_checkspur_cnt++; uint64_t cur_ntb_64 = mac_sched_get_ntb64(vdev); /* if phy hang, do not check beacon slot */ if (is_check_slot) { time_ms = min(MAC_NTB_TO_MS(spur_ctxt->next_bcn_start_ntb \ - cur_ntb_64), time_ms); } if (time_ms < MAC_CHECK_SPUR_MS) { iot_printf("mac spur req ms: %d < %d\n", time_ms, MAC_CHECK_SPUR_MS); return ERR_FAIL; } mac_set_pcs_busy(1, 1); uint32_t sts = mac_get_phy_txrx_sts(); if (MAC_PHY_RX_STS == sts) { uint32_t mac_sts = mac_dbg_bus_get_mac_sts(MAC_DEBUG_VALUE_320, \ MAC_DEBUG_VALUE_MASK_BIT_15_17); #if (MAC_CHECK_SPUR_DEBUG >= PLC_MAC_LOG_LEVEL_2) iot_printf("[mac_check_dbg] %s phy_sts:%d, mac_sts:%d\n", \ __FUNCTION__, mac_sts); #endif uint32_t bkoff1 = 0xffffffff; uint32_t bkoff2 = 0xffffffff; uint32_t bkoff3 = 0xffffffff; uint32_t bkoff4 = 0xffffffff; /* mac status -> listen status */ if (MAC_RX_LISTEN_STS == mac_sts) { /* check */ bkoff1 = mac_dbg_bus_get_mac_sts(MAC_DEBUG_VALUE_2, \ MAC_DEBUG_VALUE_MASK_BIT_13_18); bkoff2 = mac_dbg_bus_get_mac_sts(MAC_DEBUG_VALUE_12, \ MAC_DEBUG_VALUE_MASK_BIT_13_18); bkoff3 = mac_dbg_bus_get_mac_sts(MAC_DEBUG_VALUE_22, \ MAC_DEBUG_VALUE_MASK_BIT_13_18); bkoff4 = mac_dbg_bus_get_mac_sts(MAC_DEBUG_VALUE_32, \ MAC_DEBUG_VALUE_MASK_BIT_13_18); uint32_t bit_map = mac_check_value(bkoff1, bkoff2, bkoff3, bkoff4); if (iot_bitmap_cbs((uint8_t *)&bit_map, sizeof(uint32_t)) == 0) { /* bkoffx != 2 and bkoffx != 0 , do not check spur */ mac_sts = MAC_DO_NOT_BBAI_STS; } uint32_t bit_map_0_7 = bit_map & 0xf; uint32_t bit_map_8_15 = bit_map & 0xf0; if (iot_bitmap_cbs((uint8_t *)&bit_map_0_7, sizeof(uint32_t)) \ == 3 && \ iot_bitmap_cbs((uint8_t *)&bit_map_8_15, sizeof(uint32_t)) \ == 1) { /* mac in tx cca wait status, check spur */ mac_sts = MAC_TX_CCA_WAIT_STS; } else if (iot_bitmap_cbs((uint8_t *)&bit_map_0_7, sizeof(uint32_t))\ == 4 && \ iot_bitmap_cbs((uint8_t *)&bit_map_8_15, sizeof(uint32_t)) \ == 0) { /* mac in rx listen status */ mac_sts = MAC_RX_LISTEN_STS; } } /* mac status -> rx fc status */ if (MAC_RX_FC_STS == mac_sts) { mac_set_sts_idle(); while (mac_sts) { #if (MAC_CHECK_SPUR_DEBUG >= PLC_MAC_LOG_LEVEL_2) iot_printf("[mac_check_dbg] polling!\n"); #endif mac_sts = mac_dbg_bus_get_mac_sts(MAC_DEBUG_VALUE_320, \ MAC_DEBUG_VALUE_MASK_BIT_15_17); } } if ( MAC_RX_LISTEN_STS == mac_sts || \ MAC_TX_CCA_WAIT_STS == mac_sts ) { mac_set_sts_idle(); phy_reset(PHY_RST_REASON_WARM); ret = phy_chn_est_ai_by_time(time_ms); if (ret) { spur_ctxt->do_checkspur_success_cnt++; ret = ERR_OK; } else { ret = ERR_FAIL; } phy_reset(PHY_RST_REASON_WARM); mac_free_sts_idle(); } else { mac_free_sts_idle(); iot_printf("[mac_check_dbg] mac_sts:0x%x, bkoff1:0x%x, bkoff2:0x%x, "\ "bkoff3:0x%x, bkoff4:0x%x\n", mac_sts, bkoff1, bkoff2,\ bkoff3, bkoff4); mac_print_dbg_bus(0); } } else { iot_printf("[mac_check_dbg] phy_sts:0x%x\n", sts); mac_print_dbg_bus(0); } mac_set_pcs_busy(0, 0); iot_printf("[mac_check_dbg] ratio:%d%%\n", \ (spur_ctxt->do_checkspur_success_cnt*100 )/spur_ctxt->do_checkspur_cnt); uint64_t cur_ntb_out = mac_sched_get_ntb64(vdev); /* if phy hang, do not check beacon slot */ if (is_check_slot && \ cur_ntb_out > spur_ctxt->next_bcn_start_ntb) { mac_vdev_t *vdev_ptr = pdev_t->vdev[PLC_DEFAULT_VDEV]; mac_bc_time_slot_t *t_slot = &vdev_ptr->bcn_ctx.time_slot; iot_printf("slot bad: cur_ntb_h:%lu, cur_ntb_h:%lu, "\ "start_ntb_h:%lu, start_ntb_l:%lu, slot_dur:%lu, start_ntb:%lu, "\ "start_ntb_reg:%lu, dur_reg:%lu\n", \ iot_uint64_higher32(cur_ntb_64), \ iot_uint64_lower32(cur_ntb_64), \ iot_uint64_higher32(spur_ctxt->next_bcn_start_ntb), \ iot_uint64_lower32(spur_ctxt->next_bcn_start_ntb),\ t_slot->bc_period, t_slot->bp_start_ntb,\ mac_sched_get_bp_start_ntb(), \ mac_sched_get_bp_dur()); IOT_ASSERT(0); } #if (MAC_CHECK_SPUR_DEBUG >= PLC_MAC_LOG_LEVEL_2) iot_printf("[mac_check_dbg] start_ntb_h:%d, start_ntb_h:%d," "cur_ntb_h:%d, cur_ntb_l:%d,"\ "cur_ntb_out_h:%d, cur_ntb_out_l:%d\n",\ iot_uint64_higher32(spur_ctxt->next_bcn_start_ntb), iot_uint64_lower32(spur_ctxt->next_bcn_start_ntb), iot_uint64_higher32(cur_ntb_64), iot_uint64_lower32(cur_ntb_64), iot_uint64_higher32(cur_ntb_out), iot_uint64_lower32(cur_ntb_out)); #endif return ret; } uint32_t mac_check_spur_for_txhang() { uint32_t ret = ERR_FAIL; uint32_t mac_sts; mac_set_pcs_busy(1, 1); uint32_t sts = mac_get_phy_txrx_sts(); if (MAC_PHY_RX_STS == sts) { mac_sts = mac_dbg_bus_get_mac_sts(MAC_DEBUG_VALUE_320, MAC_DEBUG_VALUE_MASK_BIT_15_17); iot_printf("%s phy_sts:%d, mac_sts:%d\n", __FUNCTION__, mac_sts); uint32_t bkoff1 = 0xffffffff; uint32_t bkoff2 = 0xffffffff; uint32_t bkoff3 = 0xffffffff; uint32_t bkoff4 = 0xffffffff; /* mac status -> listen status */ if (MAC_RX_LISTEN_STS == mac_sts) { /* check */ bkoff1 = mac_dbg_bus_get_mac_sts(MAC_DEBUG_VALUE_2, MAC_DEBUG_VALUE_MASK_BIT_13_18); bkoff2 = mac_dbg_bus_get_mac_sts(MAC_DEBUG_VALUE_12, MAC_DEBUG_VALUE_MASK_BIT_13_18); bkoff3 = mac_dbg_bus_get_mac_sts(MAC_DEBUG_VALUE_22, MAC_DEBUG_VALUE_MASK_BIT_13_18); bkoff4 = mac_dbg_bus_get_mac_sts(MAC_DEBUG_VALUE_32, MAC_DEBUG_VALUE_MASK_BIT_13_18); uint32_t bit_map = mac_check_value(bkoff1, bkoff2, bkoff3, bkoff4); if (iot_bitmap_cbs((uint8_t *)&bit_map, sizeof(uint32_t)) == 0) { /* bkoffx != 2 and bkoffx != 0 , do not check spur */ mac_sts = MAC_DO_NOT_BBAI_STS; } uint32_t bit_map_0_7 = bit_map & 0xf; uint32_t bit_map_8_15 = bit_map & 0xf0; if (iot_bitmap_cbs((uint8_t *)&bit_map_0_7, sizeof(uint32_t)) == 3 && iot_bitmap_cbs((uint8_t *)&bit_map_8_15, sizeof(uint32_t)) == 1) { /* mac in tx cca wait status, check spur */ mac_sts = MAC_TX_CCA_WAIT_STS; } else if (iot_bitmap_cbs((uint8_t *)&bit_map_0_7, sizeof(uint32_t)) == 4 && iot_bitmap_cbs((uint8_t *)&bit_map_8_15, sizeof(uint32_t)) == 0) { /* mac in rx listen status */ mac_sts = MAC_RX_LISTEN_STS; } } /* mac status -> rx fc status */ if (MAC_RX_FC_STS == mac_sts) { mac_set_sts_idle(); while (mac_sts) { mac_sts = mac_dbg_bus_get_mac_sts(MAC_DEBUG_VALUE_320, MAC_DEBUG_VALUE_MASK_BIT_15_17); } } if (MAC_RX_LISTEN_STS == mac_sts || MAC_TX_CCA_WAIT_STS == mac_sts) { mac_set_sts_idle(); phy_reset(PHY_RST_REASON_WARM); iot_printf("txhang, phy reset\n"); ret = ERR_OK; phy_reset(PHY_RST_REASON_WARM); mac_free_sts_idle(); } else { mac_free_sts_idle(); iot_printf("txhang mac_sts:0x%x, bkoff1:0x%x, " "bkoff2:0x%x, bkoff3:0x%x, bkoff4:0x%x\n", mac_sts, bkoff1, bkoff2, bkoff3, bkoff4); mac_print_dbg_bus(0); } } else { iot_printf("txhang phy_sts:0x%x\n", sts); mac_print_dbg_bus(0); } mac_set_pcs_busy(0, 0); return ret; } uint32_t mac_check_spur_cert(uint32_t time_ms) { mac_pdev_t *pdev = get_pdev_ptr(PLC_PDEV_ID); return mac_check_spur(&pdev->mac_check_spur_ctxt, pdev, time_ms, false); } uint32_t mac_phy_channel_est_msg(uint32_t time_ms) { uint32_t ret = 0; mac_msg_t *msg = mac_alloc_msg(); if (msg == NULL) { IOT_ASSERT(0); ret = ERR_NOMEM; goto out; } msg->type = MAC_MSG_TYPE_PHY; msg->id = MAC_MSG_ID_CHANNEL_ESTIMATED; msg->data1 = time_ms; mac_queue_msg(msg, MAC_MSG_QUEUE_HP); out: return ret; } #else uint32_t mac_check_spur_init(mac_check_spur_ctxt_t *spur_ctxt, \ uint32_t check_spur_time_ntb) { (void)spur_ctxt; (void)check_spur_time_ntb; return 0; } uint32_t mac_check_spur_en(mac_check_spur_ctxt_t *spur_ctxt, uint32_t enable) { (void)spur_ctxt; (void)enable; return 0; } uint32_t mac_check_spur(mac_check_spur_ctxt_t *spur_ctxt, \ void *pdev, uint32_t time_ms, bool_t is_check_slot) { (void)spur_ctxt; (void)pdev; (void)time_ms; (void)is_check_slot; return 0; } uint32_t mac_check_spur_cert(uint32_t time_ms) { (void)time_ms; return 0; } void mac_print_dbg_bus(uint8_t save_flash) { (void)save_flash; } uint32_t mac_phy_channel_est_msg(uint32_t time_ms) { (void)time_ms; return 0; } uint32_t mac_check_spur_for_txhang() { return 0; } #endif