Files
kunlun/plc/halphy/hw/phy_isr.c
2024-09-28 14:24:04 +08:00

363 lines
9.5 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.
****************************************************************************/
/* os shim includes */
#include "iot_config.h"
#include "os_types.h"
#include "hw_reg_api.h"
#include "iot_mem.h"
/* plc public api includes */
#include "plc_fr.h"
#include "plc_const.h"
#include "iot_bitops.h"
/* driver includes */
#include "iot_system.h"
#include "iot_irq.h"
#include "iot_gpio_api.h"
#include "iot_board_api.h"
#include "iot_errno_api.h"
#include "pin_rf.h"
#include "mpdu_header.h"
#include "mac_sys_reg.h"
#include "plc_protocol.h"
#include "mac_raw_reg.h"
#include "mac_rawdata_hw.h"
#include "phy_reg.h"
#include "phy_bb.h"
#include "phy_phase.h"
#include "phy_isr.h"
#include "ahb.h"
#include "os_timer_api.h"
#include "phy_overstress.h"
#include "hw_phy_api.h"
iot_plc_over_stress_cb_t mac_ovr_stress_isr_cb = NULL;
/* MAC callback func register */
void register_over_stress_cb(iot_plc_over_stress_cb_t cb)
{
mac_ovr_stress_isr_cb = cb;
}
bool_t phy_overstress_is_on(void)
{
bool_t overstress_is_on = false;
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint8_t over_stress_gpio = 0;
uint32_t irq_type_reg = 0;
uint32_t reg_int = 0;
/* lic with geode in and other geode out */
if(iot_chip_check_lic()) {/* internal PA */
/* clr intr*/
reg_int = PHY_READ_REG(CFG_BB_INT_CLR_1_ADDR);
reg_int |=PHY_LIC_OVR_STRESS;
PHY_WRITE_REG(CFG_BB_INT_CLR_1_ADDR, reg_int);
/* check intr src */
irq_type_reg = PHY_READ_REG(CFG_BB_INT_RAW_1_ADDR);
if(irq_type_reg & PHY_LIC_OVR_STRESS){
return true;
} else {
return false;
}
} else {/* external PA */
over_stress_gpio = iot_board_get_gpio(GPIO_GEODE_OVT);
if(iot_gpio_value_get(over_stress_gpio)) {
return false;
} else {
return true;
}
}
#endif
return overstress_is_on;
}
/* TODO: use macro distinguish WARID, as WAR_BUGID_244 in iot_config.h */
uint32_t IRAM_ATTR phy_get_hw_interrupt_type(void)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t irq_type_reg = 0;
uint32_t irq_type = 0;
/* get int 1 mask */
irq_type_reg = PHY_READ_REG(CFG_BB_INT_MASK_1_ADDR);
if(irq_type_reg & PHY_LIC_OVR_STRESS){
irq_type |= INTR_TYPE_PHY_LIC_OVR_STRESS;
}
return irq_type;
#else
return 0;
#endif
}
void IRAM_ATTR phy_disable_hw_interrupt(uint32_t irq_type)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t reg_int = 0;
/* disable int 1 */
if (irq_type & INTR_TYPE_PHY_LIC_OVR_STRESS) {
reg_int = PHY_READ_REG(CFG_BB_INT_EN_1_ADDR);
reg_int &= (~PHY_LIC_OVR_STRESS);
PHY_WRITE_REG(CFG_BB_INT_EN_1_ADDR, reg_int);
}
#else
(void)irq_type;
#endif
return;
}
void IRAM_ATTR phy_clear_hw_interrupt(uint32_t irq_type)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t reg_int = 0;
/* clear int 1 */
if (irq_type & INTR_TYPE_PHY_LIC_OVR_STRESS) {
reg_int = PHY_READ_REG(CFG_BB_INT_CLR_1_ADDR);
reg_int |=PHY_LIC_OVR_STRESS;
PHY_WRITE_REG(CFG_BB_INT_CLR_1_ADDR, reg_int);
}
#else
(void)irq_type;
#endif
}
void IRAM_ATTR phy_enable_hw_interrupt(uint32_t irq_type)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t reg_int = 0;
/* enable int 1 */
if (irq_type & INTR_TYPE_PHY_LIC_OVR_STRESS) {
reg_int = PHY_READ_REG(CFG_BB_INT_EN_1_ADDR);
reg_int |=PHY_LIC_OVR_STRESS;
PHY_WRITE_REG(CFG_BB_INT_EN_1_ADDR, reg_int);
}
#else
(void)irq_type;
#endif
return;
}
uint32_t IRAM_ATTR phy_interrupt_handler(uint32_t vector, iot_addrword_t data)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t isr_flag = 0;
isr_flag = phy_get_hw_interrupt_type();
/* clear cpu0 int */
phy_clear_hw_interrupt(isr_flag);
/* disable interrupt mask */
phy_disable_hw_interrupt(isr_flag);
/* turn down gain */
if (isr_flag & INTR_TYPE_PHY_LIC_OVR_STRESS) {
/* update cnt */
phy_add_overstress_cnt();
/* turn down power */
if (!g_phy_ctxt.indep.ovs_ctxt.ovr_stress) {
/* update global flag */
g_phy_ctxt.indep.ovs_ctxt.ovr_stress = 1;
}
/* mac callback */
if (mac_ovr_stress_isr_cb != NULL) {
mac_ovr_stress_isr_cb(NULL, 1);
}
}
if (isr_flag & INTR_TYPE_PHY_LIC_OVR_STRESS){
/* disable over stress interrupt */
isr_flag &= ~INTR_TYPE_PHY_LIC_OVR_STRESS;
phy_enable_hw_interrupt(isr_flag);
}
else{
phy_enable_hw_interrupt(isr_flag);
}
#else
(void)vector;
(void)data;
#endif
return ERR_OK;
}
void phy_gpio_interrupt_handler(int arg)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint8_t over_stress_gpio = iot_board_get_gpio(GPIO_GEODE_OVT);
/* disable overstress gpio interrupt */
iot_gpio_interrupt_enable(over_stress_gpio, 0);
/* add event cnt */
phy_add_overstress_cnt();
/* turn down tx power with rms */
if(!g_phy_ctxt.indep.ovs_ctxt.ovr_stress) {
/* update global flag */
g_phy_ctxt.indep.ovs_ctxt.ovr_stress = 1;
}
/* mac callback */
if(mac_ovr_stress_isr_cb != NULL){
mac_ovr_stress_isr_cb(NULL, 0);
}
#endif
(void)arg;
return;
}
uint32_t phy_gpio_interrupt_init()
{
uint32_t ret = ERR_FAIL;
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint8_t over_stress_gpio = iot_board_get_gpio(GPIO_GEODE_OVT);
ret = iot_gpio_open_as_interrupt(over_stress_gpio);
ret |= iot_gpio_interrupt_config(over_stress_gpio,
GPIO_INT_LEVEL_LOW, phy_gpio_interrupt_handler, 0,
GPIO_INT_FUNC_ENABLE_AUTOSTOP);
ret |= iot_gpio_interrupt_enable(over_stress_gpio, 1);
if(ret){
iot_gpio_close(over_stress_gpio);
}
#endif
return ret;
}
static void phy_isr_clean(void)
{
/* disable all interrupt and clean up any pending interrupt */
PHY_WRITE_REG(CFG_BB_INT_EN_0_ADDR, 0);
PHY_WRITE_REG(CFG_BB_INT_EN_1_ADDR, 0);
PHY_WRITE_REG(CFG_BB_INT_EN_2_ADDR, 0);
//INT_EN_3 map to cpu1
/* clean up all pending interrupt */
PHY_WRITE_REG(CFG_BB_INT_CLR_0_ADDR, BB_INT_CLR_0_MASK);
PHY_WRITE_REG(CFG_BB_INT_CLR_1_ADDR, BB_INT_CLR_1_MASK);
PHY_WRITE_REG(CFG_BB_INT_CLR_2_ADDR, BB_INT_CLR_2_MASK);
}
void phy_isr_clean_cpu1(void)
{
/* disable all interrupt and clean up any pending interrupt */
PHY_WRITE_REG(CFG_BB_INT_EN_3_ADDR, 0);
/* clean up all pending interrupt */
PHY_WRITE_REG(CFG_BB_INT_CLR_3_ADDR, BB_INT_CLR_3_MASK);
}
void phy_isr_init()
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
iot_irq_t phy_fd_fc_err_irqhdl;
iot_irq_t phy_lic_ovr_stress_irqhdl;
/* reset phy interrupt reg */
phy_isr_clean();
/* k48 or k68 */
if(iot_chip_check_lic()) {/* internal PA */
phy_lic_ovr_stress_irqhdl = \
iot_interrupt_create(IRQ_NUM_PHY_LIC_OVR_STRESS, HAL_INTR_PRI_0,
0, phy_interrupt_handler);
iot_interrupt_attach(phy_lic_ovr_stress_irqhdl);
iot_interrupt_unmask(phy_lic_ovr_stress_irqhdl);
} else {/* external PA */
phy_gpio_interrupt_init();
}
phy_fd_fc_err_irqhdl = \
iot_interrupt_create(HAL_VECTOR_PHY_2, HAL_INTR_PRI_6,
0, phy_interrupt_handler);
iot_interrupt_attach(phy_fd_fc_err_irqhdl);
iot_interrupt_unmask(phy_fd_fc_err_irqhdl);
#endif
return;
}
void phy_isr_start()
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t reg_int;
/* bind phy int 1 */
if(iot_chip_check_lic()){/* internal PA */
reg_int = PHY_READ_REG(CFG_BB_INT_EN_1_ADDR);
reg_int |= PHY_LIC_OVR_STRESS;
PHY_WRITE_REG(CFG_BB_INT_EN_1_ADDR, reg_int);
}
#endif
return;
}
void phy_isr_start_cpu1(void)
{
#if HW_PLATFORM >= HW_PLATFORM_FPGA
uint32_t reg_int = 0;
phy_isr_clean_cpu1();
/* TODO: enable isr need use api phy_enable_hw_interrupt_cpu1() */
/* bind phy int 3 */
reg_int = PHY_RECV_FD_FC_OK;
reg_int |= PHY_RECV_FD_FC_FAIL;
reg_int |= PHY_TX_FD_TX_DONE;
#if ENA_WAR_NSG_EXTMI || MAC_SYM_NUM_FIX
reg_int |= PHY_RECV_FD_CH_EST_DONE;
#endif/* ENA_WAR_NSG_EXTMI || MAC_SYM_NUM_FIX */
#if ENA_WAR_NSG_EXTMI
reg_int |= PHY_RECV_FD_PB_OK;
reg_int |= PHY_RECV_FD_PB_FAIL;
reg_int |= PHY_RECV_FC_RAW_RECEIVE;
#endif/* ENA_WAR_NSG_EXTMI */
#if (ENA_WAR_NSG_EXTMI || ENA_SW_SYNC_PPM_WAR)
reg_int |= PHY_TX_FD_INSERT_PREAM_DONE;
#endif
#if (ENA_WAR_SPG_TX_OK || DEBUG_NID_ERR || ENA_CCO_RX_THR_PHASE_CHANGE)
reg_int |= PHY_TX_TD_FC_DONE;
#endif
#if ENA_WAR_244
reg_int |= PHY_FD_TX_ABORT;
reg_int |= PHY_FD_TX_STUCK;
reg_int |= PHY_TX_TD_START;
#endif
#if MAC_SYM_NUM_FIX || MAC_TIMESTAMPING || ENA_CCO_RX_THR_PHASE_CHANGE
reg_int |= PHY_RECV_FD_PLD_OK;
reg_int |= PHY_RECV_FD_PLD_FAIL;
#endif
PHY_WRITE_REG(CFG_BB_INT_EN_3_ADDR, reg_int);
#endif
return;
}