Files
kunlun/plc/halmac/hw3/rx/mac_rf_rx_buf_ring.c
2024-09-28 14:24:04 +08:00

574 lines
17 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 "mac_rf_rx_buf_ring.h"
#include "iot_errno.h"
#include "iot_utils.h"
#include "iot_io.h"
#include "plc_utils.h"
#include "plc_mac_cfg.h"
#include "mac.h"
#include "plc_fr.h"
#include "plc_const.h"
#include "mac_rf_pdev.h"
#include "mac_rx_buf_ring.h"
#include "mac_rf_isr.h"
#include "mac_rf_rx_hw.h"
#include "math_log10.h"
#if HPLC_RF_DEV_SUPPORT
#if HW_PLATFORM >= HW_PLATFORM_FPGA
#include "hw_reg_api.h"
#include "rf_mac_rx_reg.h"
#include "rf_mac_int.h"
/* get rf ring buffer read index */
#define RF_RX_RING_GET_RD_IDX(ring_id) \
REG_FIELD_GET(CFG_RF_RING##ring_id##_RD_IDX, \
RGF_RF_RX_READ_REG(RF_BUFFER_RING##ring_id##_2_ADDR))
/* set rf ring buffer read index */
#define RF_RX_RING_SET_RD_IDX(ring_id, value) \
do { \
uint32_t __tmp = RGF_RF_RX_READ_REG( \
RF_BUFFER_RING##ring_id##_2_ADDR); \
REG_FIELD_SET(CFG_RF_RING##ring_id##_RD_IDX, \
__tmp, value); \
RGF_RF_RX_WRITE_REG(RF_BUFFER_RING##ring_id##_2_ADDR, __tmp); \
} while (0)
/* get rf ring buffer write index */
#define RF_RX_RING_GET_WR_IDX(ring_id, reg_idx) \
REG_FIELD_GET(RO_RF_RING##ring_id##_MPDU_BUF_WR_IDX, \
RGF_RF_RX_READ_REG(RX_BUF_RING_WR_IDX_##reg_idx##_ADDR))
#define RF_RX_RING_SET_FILTER(ring_id, value) \
do { \
uint32_t __tmp = RGF_RF_RX_READ_REG( \
RF_BUFFER_RING##ring_id##_1_ADDR); \
REG_FIELD_SET(CFG_RF_RING##ring_id##_FILTER, \
__tmp, value); \
RGF_RF_RX_WRITE_REG(RF_BUFFER_RING##ring_id##_1_ADDR, __tmp); \
} while (0)
void rf_rx_ring_clr_overflow_int(uint32_t rid)
{
//TODO: add code
(void)rid;
}
uint32_t rf_rx_ring_get_mpdu_int_status(void)
{
uint32_t tmp;
tmp = mac_rf_get_share_interrupt_sts();
/* clear interrupt status */
mac_rf_clear_share_interrupt(RF_MAC_INT_RX_RING_BIT_MASK & tmp);
return ((tmp & RF_MAC_INT_RX_RING_BIT_MASK)
>> RF_MAC_INT_RX_RING_BIT_OFFSET);
}
void rf_rx_ring_clr_mpdu_int(uint32_t rid)
{
if (rid > MAX_RF_RX_RING_NUM) {
return;
}
mac_rf_clear_share_interrupt(1 << (rid + RF_MAC_INT_RX_RING_BIT_OFFSET));
}
/* get ring rd idx */
uint32_t rf_rx_ring_get_rd_idx(rx_buf_ring_t *rf_rx_ring)
{
IOT_ASSERT(rf_rx_ring && (rf_rx_ring->ring_id < MAX_RF_RX_RING_NUM));
switch (rf_rx_ring->ring_id) {
case 0:
return RF_RX_RING_GET_RD_IDX(0);
case 1:
return RF_RX_RING_GET_RD_IDX(1);
case 2:
return RF_RX_RING_GET_RD_IDX(2);
case 3:
return RF_RX_RING_GET_RD_IDX(3);
case 4:
return RF_RX_RING_GET_RD_IDX(4);
case 5:
return RF_RX_RING_GET_RD_IDX(5);
default:
break;
}
return 0;
}
/* set ring rd idx */
void rf_rx_ring_set_rd_idx(rx_buf_ring_t *rf_rx_ring, uint32_t value)
{
IOT_ASSERT(rf_rx_ring && (rf_rx_ring->ring_id < MAX_RF_RX_RING_NUM));
switch (rf_rx_ring->ring_id) {
case 0:
RF_RX_RING_SET_RD_IDX(0, value);
break;
case 1:
RF_RX_RING_SET_RD_IDX(1, value);
break;
case 2:
RF_RX_RING_SET_RD_IDX(2, value);
break;
case 3:
RF_RX_RING_SET_RD_IDX(3, value);
break;
case 4:
RF_RX_RING_SET_RD_IDX(4, value);
break;
case 5:
RF_RX_RING_SET_RD_IDX(5, value);
break;
default:
break;
}
}
/* get ring rd idx */
uint32_t rf_rx_ring_get_wr_idx(rx_buf_ring_t *rf_rx_ring)
{
IOT_ASSERT(rf_rx_ring && (rf_rx_ring->ring_id < MAX_RF_RX_RING_NUM));
switch (rf_rx_ring->ring_id) {
case 0:
return RF_RX_RING_GET_WR_IDX(0, 0);
case 1:
return RF_RX_RING_GET_WR_IDX(1, 0);
case 2:
return RF_RX_RING_GET_WR_IDX(2, 0);
case 3:
return RF_RX_RING_GET_WR_IDX(3, 1);
case 4:
return RF_RX_RING_GET_WR_IDX(4, 1);
case 5:
return RF_RX_RING_GET_WR_IDX(5, 1);
default:
IOT_ASSERT(0);
break;
}
return 0;
}
uint8_t rf_rx_ring_set_filter(rx_buf_ring_t *rf_rx_ring)
{
IOT_ASSERT(rf_rx_ring && (rf_rx_ring->ring_id < MAX_RF_RX_RING_NUM));
switch(rf_rx_ring->ring_id) {
case 0:
RF_RX_RING_SET_FILTER(0, rf_rx_ring->filter);
break;
case 1:
RF_RX_RING_SET_FILTER(1, rf_rx_ring->filter);
break;
case 2:
RF_RX_RING_SET_FILTER(2, rf_rx_ring->filter);
break;
case 3:
RF_RX_RING_SET_FILTER(3, rf_rx_ring->filter);
break;
case 4:
RF_RX_RING_SET_FILTER(4, rf_rx_ring->filter);
break;
case 5:
RF_RX_RING_SET_FILTER(5, rf_rx_ring->filter);
break;
default:
IOT_ASSERT(0);
}
return 0;
}
/* enable rx ring */
void mac_rf_rx_ring_enable(rx_buf_ring_t *rf_rx_ring, uint32_t enable)
{
uint32_t tmp;
IOT_ASSERT(rf_rx_ring && (rf_rx_ring->ring_id < MAX_RF_RX_RING_NUM));
switch (rf_rx_ring->ring_id) {
case 0:
tmp = RGF_RF_RX_READ_REG(RF_BUFFER_RING0_2_ADDR);
REG_FIELD_SET(CFG_RF_RING0_EN, tmp, enable);
RGF_RF_RX_WRITE_REG(RF_BUFFER_RING0_2_ADDR, tmp);
break;
case 1:
tmp = RGF_RF_RX_READ_REG(RF_BUFFER_RING1_2_ADDR);
REG_FIELD_SET(CFG_RF_RING1_EN, tmp, enable);
RGF_RF_RX_WRITE_REG(RF_BUFFER_RING1_2_ADDR, tmp);
break;
case 2:
tmp = RGF_RF_RX_READ_REG(RF_BUFFER_RING2_2_ADDR);
REG_FIELD_SET(CFG_RF_RING2_EN, tmp, enable);
RGF_RF_RX_WRITE_REG(RF_BUFFER_RING2_2_ADDR, tmp);
break;
case 3:
tmp = RGF_RF_RX_READ_REG(RF_BUFFER_RING3_2_ADDR);
REG_FIELD_SET(CFG_RF_RING3_EN, tmp, enable);
RGF_RF_RX_WRITE_REG(RF_BUFFER_RING3_2_ADDR, tmp);
break;
case 4:
tmp = RGF_RF_RX_READ_REG(RF_BUFFER_RING4_2_ADDR);
REG_FIELD_SET(CFG_RF_RING4_EN, tmp, enable);
RGF_RF_RX_WRITE_REG(RF_BUFFER_RING4_2_ADDR, tmp);
break;
case 5:
tmp = RGF_RF_RX_READ_REG(RF_BUFFER_RING5_2_ADDR);
REG_FIELD_SET(CFG_RF_RING5_EN, tmp, enable);
RGF_RF_RX_WRITE_REG(RF_BUFFER_RING5_2_ADDR, tmp);
break;
default:
break;
}
}
/* fill in the ring cfg */
void rf_rx_ring_fill_hw_cfg(rx_buf_ring_t *rf_rx_ring)
{
uint32_t tmp;
uint32_t ring_addr0, ring_addr1, ring_addr3;
IOT_ASSERT(rf_rx_ring && (rf_rx_ring->ring_id < MAX_PLC_RX_RING_NUM));
switch (rf_rx_ring->ring_id) {
case 0:
ring_addr0 = RF_BUFFER_RING0_0_ADDR;
ring_addr1 = RF_BUFFER_RING0_1_ADDR;
ring_addr3 = RF_BUFFER_RING0_3_ADDR;
break;
case 1:
ring_addr0 = RF_BUFFER_RING1_0_ADDR;
ring_addr1 = RF_BUFFER_RING1_1_ADDR;
ring_addr3 = RF_BUFFER_RING1_3_ADDR;
break;
case 2:
ring_addr0 = RF_BUFFER_RING2_0_ADDR;
ring_addr1 = RF_BUFFER_RING2_1_ADDR;
ring_addr3 = RF_BUFFER_RING2_3_ADDR;
break;
case 3:
ring_addr0 = RF_BUFFER_RING3_0_ADDR;
ring_addr1 = RF_BUFFER_RING3_1_ADDR;
ring_addr3 = RF_BUFFER_RING3_3_ADDR;
break;
case 4:
ring_addr0 = RF_BUFFER_RING4_0_ADDR;
ring_addr1 = RF_BUFFER_RING4_1_ADDR;
ring_addr3 = RF_BUFFER_RING4_3_ADDR;
break;
case 5:
default:
ring_addr0 = RF_BUFFER_RING5_0_ADDR;
ring_addr1 = RF_BUFFER_RING5_1_ADDR;
ring_addr3 = RF_BUFFER_RING5_3_ADDR;
break;
}
/* set ring buf array ptr */
RGF_RF_RX_WRITE_REG(ring_addr0, (uint32_t)rf_rx_ring->buf_list);
/* set ring size and buf length */
tmp = RGF_RF_RX_READ_REG(ring_addr1);
REG_FIELD_SET(CFG_RF_RING0_BUF_SIZE, tmp, iot_ceil(rf_rx_ring->buf_sz, 4));
REG_FIELD_SET(CFG_RF_RING0_BUF_NUM, tmp, rf_rx_ring->ring_sz);
/* re-enable ring, disable clr wr idx */
REG_FIELD_SET(CFG_RF_RING0_BUF_REENA_CLR_EN, tmp, 0);
RGF_RF_RX_WRITE_REG(ring_addr1, tmp);
rf_rx_ring_set_filter(rf_rx_ring);
/* set rd idx = 0 as default */
rf_rx_ring_set_rd_idx(rf_rx_ring, 0);
/* set desc and payload offset */
tmp = RGF_RF_RX_READ_REG(ring_addr3);
REG_FIELD_SET(CFG_RF_RING0_DESC_EN, tmp,
rf_rx_ring->config[CONFIG_RX_DESC].enable);
REG_FIELD_SET(CFG_RF_RING0_PAYLOAD_EN, tmp,
rf_rx_ring->config[CONFIG_PAYLOAD].enable);
REG_FIELD_SET(CFG_RF_RING0_DESC_OFFSET, tmp,
iot_ceil(rf_rx_ring->config[CONFIG_RX_DESC].offset, 4));
REG_FIELD_SET(CFG_RF_RING0_PAYLOAD_OFFSET, tmp,
iot_ceil(rf_rx_ring->config[CONFIG_PAYLOAD].offset, 4));
RGF_RF_RX_WRITE_REG(ring_addr3, tmp);
}
rx_buf_ring_t *mac_rf_rx_get_ring(void *rf_pdev, uint32_t index)
{
if (index >= MAX_RF_RX_RING_NUM) {
IOT_ASSERT(0);
return NULL;
}
mac_rf_pdev_t *rf_pdev_ptr = (mac_rf_pdev_t *)rf_pdev;
IOT_ASSERT(rf_pdev_ptr);
return &rf_pdev_ptr->ring_hdl.ring[index];
}
#endif /* HW_PLATFORM >= HW_PLATFORM_FPGA */
#if ((HW_PLATFORM >= HW_PLATFORM_FPGA) && (HPLC_BBCPU_CALC_SNR_RSSI == 0))
static float mac_rf_get_snr(uint32_t option, uint32_t raw_reg1,
uint16_t *raw_snr)
{
float snr;
float rdata = (float)raw_reg1;
float rawdata = (1<<16)*1.0/(rdata*1.0/((option==3) ? 36 : 96));
float tmp = rawdata * 10 + 0.5;
*raw_snr = (uint16_t)(min(0xFFFF, (uint32_t)tmp));
if (rawdata >= 1) {
snr = 10*mlog10(rawdata);
} else {
snr = 10*na_mlog10(rawdata);
}
return snr;
}
static void mac_rf_get_snr_rssi(uint32_t option, uint32_t raw_reg1,
uint32_t raw_reg2, uint32_t raw_reg3, int8_t *snr, int8_t *rssi,
uint8_t *gain, uint16_t *raw_snr)
{
/* X can be got by calibration */
#define X_CALIBRATION 60
float snr_tmp = mac_rf_get_snr(option, raw_reg1, raw_snr);
float rdata1 = (float)raw_reg2;
uint32_t rdata2 = raw_reg3;
float rssi_tmp = 10*mlog10(rdata1*1.0) - X_CALIBRATION - (rdata2 & 0xFF) -
((rdata2 >> 8) & 0xFF) + ((snr_tmp < 0) ? snr_tmp: 0);
/* 13 - 74 */
*gain = (uint8_t)((rdata2 & 0xFF) + ((rdata2 >> 8) & 0xFF));
*snr = (int8_t)snr_tmp;
*rssi = (int8_t)rssi_tmp;
}
static void mac_rf_cal_snr_rssi_gain(rf_rx_attention *att,
rf_rx_mpdu_start *mpdu_st)
{
IOT_ASSERT(att && mpdu_st);
/* get record raw register */
uint32_t rawreg1 = mpdu_st->raw_snr_rssi_reg1;
uint32_t rawreg2 = mpdu_st->raw_snr_rssi_reg2;
uint32_t rawreg3 = mpdu_st->raw_snr_rssi_reg3;
/* clear record raw register */
mpdu_st->raw_snr_rssi_reg1 = 0;
mpdu_st->raw_snr_rssi_reg2 = 0;
mpdu_st->raw_snr_rssi_reg3 = 0;
int8_t snr, rssi;
uint8_t rx_gain;
uint16_t raw_snr;
/* calculate snr, rssi rx gain, raw snr */
mac_rf_get_snr_rssi(att->option, rawreg1, rawreg2, rawreg3,
&snr, &rssi, &rx_gain, &raw_snr);
/* record snr */
mac_rf_rx_mpdu_st_set_avg_snr(mpdu_st, snr);
/* record raw snr */
mac_rf_rx_mpdu_st_set_raw_snr(mpdu_st, raw_snr);
/* record rssi */
mac_rf_rx_mpdu_st_set_rssi(mpdu_st, rssi);
/* record rx gain */
mac_rf_rx_mpdu_st_set_rx_gain(mpdu_st, rx_gain);
}
#else /* (HW_PLATFORM >= HW_PLATFORM_FPGA) && (HPLC_BBCPU_CALC_SNR_RSSI == 0) */
static void mac_rf_cal_snr_rssi_gain(rf_rx_attention *att,
rf_rx_mpdu_start *mpdu_st)
{
(void)att;
(void)mpdu_st;
}
#endif /* (HW_PLATFORM >= HW_PLATFORM_FPGA) && (HPLC_BBCPU_CALC_SNR_RSSI == 0) */
void mac_rf_rx_all_ring_enable(void *rf_pdev)
{
rx_buf_ring_t *rf_ring;
mac_rf_pdev_t *rf_pdev_ptr = (mac_rf_pdev_t *)rf_pdev;
IOT_ASSERT(rf_pdev_ptr);
for (uint32_t i = 0; i < MAX_RF_RX_RING_NUM; i++){
/* get ring pointer */
rf_ring = mac_rf_rx_get_ring(rf_pdev, i);
/* enable ring */
if(rf_ring->cfg_enabled == 1) {
mac_rf_rx_ring_enable(rf_ring, 1);
}
}
return;
}
void mac_rf_rx_all_ring_disable(void *rf_pdev)
{
rx_buf_ring_t *rf_ring;
mac_rf_pdev_t *rf_pdev_ptr = (mac_rf_pdev_t *)rf_pdev;
IOT_ASSERT(rf_pdev_ptr);
for (uint32_t i = 0; i < MAX_RF_RX_RING_NUM; i++){
/* get ring pointer */
rf_ring = mac_rf_rx_get_ring(rf_pdev, i);
if(rf_ring->cfg_enabled == 1){
mac_rf_rx_ring_enable(rf_ring, 0);
if (rf_pdev_ptr->rx) {
mac_rf_rx_hw_mpdu_internal(rf_pdev_ptr, i, MAX_RX_QUOTA_MS);
}
}
}
return;
}
uint32_t mac_rf_rx_ring_ctxt_init(mac_rx_ring_ctxt_t *rf_ring_ctxt)
{
uint32_t ret;
/* init only one rx ring temply */
ring_config config_sof[] =
{
{ CONFIG_RX_DESC, RF_RX_ATTENTION_OFFSET, 1 },
{ CONFIG_RX_MPDU_START, 0, 0 },
{ CONFIG_RX_MPDU_END, 0, 0 },
{ CONFIG_RX_PB_START, 0, 0 },
{ CONFIG_RX_PB_END, 0, 0 },
{ CONFIG_FC, 0, 0 },
{ CONFIG_PAYLOAD, RF_RX_PB_PAYLOAD_OFFSET, 1 }
};
rf_ring_ctxt->mpdu_pb_cb = NULL;
ret = rf_rx_buf_ring_init(&rf_ring_ctxt->ring[RF_RING_0], RF_RING_0,
(uint32_t)RF_SHORT_RX_BUF_COUNT, PLC_SHORT_BUF_SIZE, NULL,
config_sof, 0, 0);
if (ERR_OK != ret) {
/* return error */
goto out;
}
/*init ring1 bufsize = 136*/
ret = rf_rx_buf_ring_init(&rf_ring_ctxt->ring[RF_RING_1], RF_RING_1,
(uint32_t)RF_SMALL_RX_BUF_COUNT, PLC_SMALL_BUF_SIZE, NULL,
config_sof, 0, 0);
out:
return ret;
}
/* init and put on the buf_list */
uint32_t rf_rx_buf_ring_init(rx_buf_ring_t *rf_rx_ring, uint32_t ring_id,
uint32_t ring_sz, uint32_t buf_sz, rx_low_watermark_callback cb,
ring_config *cfg, uint8_t bufsz_filter_sel, uint8_t filter)
{
iot_pkt_t *iot_pkt;
uint8_t *data_ptr;
if(!rf_rx_ring->buf_list){
rf_rx_ring->buf_list =
(uint8_t**)os_mem_malloc(PLC_MAC_RX_RING_MID,
ring_sz * mac_rx_get_ring_buf_desc_size());
if (!rf_rx_ring->buf_list) {
return ERR_NOMEM;
}
for (uint32_t i = 0; i < ring_sz; i++) {
iot_pkt = iot_pkt_alloc(buf_sz, PLC_MAC_RX_HW_MID);
if (!iot_pkt) {
/* alloc failed */
IOT_ASSERT(0);
return ERR_NOMEM;
}
else {
/* alloc successful */
/* set and check data field len */
data_ptr = iot_pkt_put(iot_pkt, buf_sz);
IOT_ASSERT(data_ptr);
mac_rx_set_ring_buf_list(rf_rx_ring->buf_list, ring_sz,
i, iot_pkt);
}
}
}
rf_rx_ring->read_idx = 0;
rf_rx_ring->write_idx = 0;
rf_rx_ring->ring_id = ring_id;
rf_rx_ring->water_mark_buf_num = ring_sz << 2; // 1/4 of ring_sz
rf_rx_ring->overflow = 0;
rf_rx_ring->bufsz_filter_sel = bufsz_filter_sel;
rf_rx_ring->filter = filter;
rf_rx_ring->buf_sz = buf_sz;
rf_rx_ring->ring_sz = ring_sz;
rf_rx_ring->config[CONFIG_RX_DESC] = cfg[CONFIG_RX_DESC];
rf_rx_ring->config[CONFIG_PAYLOAD] = cfg[CONFIG_PAYLOAD];
rf_rx_ring->cb = cb;
rf_rx_ring->cfg_enabled = 1;
rf_rx_ring_fill_hw_cfg(rf_rx_ring);
return ERR_OK;
}
/* FW call this to reap data down and repurnish the buf */
uint32_t rf_pop_buf_from_ring(rx_buf_ring_t *rf_rx_ring, uint32_t num,
iot_pkt_t **buf_array)
{
uint32_t aval_num = 0;
uint32_t read_num = 0;
iot_pkt_t *p_buf = NULL;
uint8_t *rx_buf_addr;
if (!rf_rx_ring)
{
return read_num;
}
/* read rd and wr idx */
rf_rx_ring->write_idx = rf_rx_ring_get_wr_idx(rf_rx_ring);
rf_rx_ring->read_idx = rf_rx_ring_get_rd_idx(rf_rx_ring);
(aval_num = (rf_rx_ring->write_idx - rf_rx_ring->read_idx)) < 0 ? \
aval_num += (rf_rx_ring->ring_sz) : aval_num;
read_num = min(aval_num, num);
for (uint32_t i = 0; i < read_num; i++)
{
/* get the iot_pkt_t ptr and reap the buf */
buf_array[i] = mac_rx_get_ring_buf_list(rf_rx_ring);
/* repurnish another buf */
p_buf = iot_pkt_alloc(rf_rx_ring->buf_sz, PLC_MAC_RF_MID);
if (!p_buf) {
//IOT_ASSERT(0);
return i;
}
rf_rx_buf_hdr_t *rf_rx_buf =
(rf_rx_buf_hdr_t *)iot_pkt_data(buf_array[i]);
/* calculate snr/rssi/rx gain */
mac_rf_cal_snr_rssi_gain(&rf_rx_buf->att, &rf_rx_buf->mpdu_st);
rx_buf_addr = iot_pkt_put(p_buf, rf_rx_ring->buf_sz);
IOT_ASSERT(rx_buf_addr);
/* clear the mpdu_done bit, sometimes HW move the
* wr idx without write to the rx buf when rx abort
* happen
*/
((rf_rx_attention*)(iot_pkt_data(p_buf)))->rx_mpdu_done = 0;
mac_rx_set_ring_buf_list(rf_rx_ring->buf_list, rf_rx_ring->ring_sz,
rf_rx_ring->read_idx, p_buf);
if (++rf_rx_ring->read_idx == rf_rx_ring->ring_sz) {
rf_rx_ring->read_idx = 0;
}
rf_rx_ring_set_rd_idx(rf_rx_ring, rf_rx_ring->read_idx);
}
return read_num;
}
#endif /* HPLC_RF_DEV_SUPPORT */