432 lines
12 KiB
C
Executable File
432 lines
12 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 "os_types.h"
|
|
#include "os_utils_api.h"
|
|
#include "iot_config.h"
|
|
#include "iot_errno_api.h"
|
|
#include "iot_config_api.h"
|
|
#include "iot_io_api.h"
|
|
#include "clk.h"
|
|
|
|
#include "hw_reg_api.h"
|
|
#include "phy_dfe_reg.h"
|
|
#include "ahb.h"
|
|
#include "ada_reg.h"
|
|
#include "phy_bb.h"
|
|
#include "phy_phase.h"
|
|
#include "phy_ana.h"
|
|
#include "hw_phy_init.h"
|
|
#include "granite_reg.h"
|
|
#include "mac.h"
|
|
#include "mac_msg.h"
|
|
#include "mac_pdev.h"
|
|
#include "mac_vdev.h"
|
|
#include "mac_pm.h"
|
|
#include "mac_tx_power.h"
|
|
#include "mac_hw_tsfm.h"
|
|
#include "iot_system.h"
|
|
#include "iot_dbglog_api.h"
|
|
#include "iot_dbglog_parser.h"
|
|
#include "iot_module_api.h"
|
|
|
|
#if PLC_SUPPORT_HW_TSFM_PA
|
|
|
|
#include "iot_gptmr_api.h"
|
|
|
|
#define MAC_HW_TSFM_DBG_ENA 0
|
|
|
|
#if MAC_HW_TSFM_DBG_ENA
|
|
#define mac_hw_tsfm_dbg_print(fmt, ...) iot_printf(fmt, ##__VA_ARGS__)
|
|
#else
|
|
#define mac_hw_tsfm_dbg_print(fmt, ...)
|
|
#endif
|
|
|
|
#define mac_hw_tsfm_timer_is_valid(id) \
|
|
((((id) >= GP_TIMER_COUNT) || (0 == (id))) ? 0 : 1)
|
|
|
|
#define mac_hw_tsfm_signal_tx(tone_num) phy_dfe_tone_cfg(1, tone_num, 0)
|
|
|
|
#define mac_hw_tsfm_signal_idle() \
|
|
phy_dfe_tone_cfg(0, 0, 0)
|
|
|
|
#define mac_hw_tsfm_ctxt_get() \
|
|
(mac_hw_tsfm_ctxt_t *)g_mac_pdev[PLC_PDEV_ID]->hw_tsfm
|
|
|
|
static void mac_hw_tsfm_complete(void)
|
|
{
|
|
mac_hw_tsfm_ctxt_t *tsfm = mac_hw_tsfm_ctxt_get();
|
|
IOT_ASSERT(tsfm);
|
|
|
|
/* tx complete. stop timer */
|
|
iot_gp_timer_stop(tsfm->timer_id);
|
|
/* disable phy atten */
|
|
mac_hw_tsfm_signal_idle();
|
|
tsfm->tsfm_mode = 0;
|
|
|
|
/* restore backup */
|
|
if (IOT_SUPPORT_RATE_SR == tsfm->backup.tx_rate_mode_ovr) {
|
|
phy_tx_rate_mode_ovr_set(0, tsfm->backup.tx_rate_mode_ovr);
|
|
} else {
|
|
phy_tx_rate_mode_ovr_set(1, tsfm->backup.tx_rate_mode_ovr);
|
|
}
|
|
|
|
/* disable phy tx force */
|
|
phy_set_tx_force_enable(0);
|
|
/* reset phy */
|
|
phy_reset(PHY_RST_REASON_COLD);
|
|
|
|
/* restore ada clk config */
|
|
enable_ada(tsfm->backup.ada_eb);
|
|
/* restore ada power on config */
|
|
phy_ada_enable(tsfm->backup.ada_power_on);
|
|
|
|
/* restore tx power */
|
|
phy_ana_pga_gain_set(tsfm->backup.ana_pga_gain);
|
|
phy_tx_gain_factor_set((uint8_t)tsfm->backup.tx_pwr_scale_factor);
|
|
|
|
/* record tx execute count to flash */
|
|
tsfm->logger.tx_complete_cnt++;
|
|
iot_dbglog_input(PLC_MAC_HW_TSFM_MID, DBGLOG_ERR, IOT_MAC_HW_TSFM_ID, 6,
|
|
tsfm->config.data[0], tsfm->config.data[1], tsfm->config.data[2],
|
|
tsfm->config.data[3], tsfm->logger.tx_req_cnt,
|
|
tsfm->logger.tx_complete_cnt);
|
|
iot_printf("mac_hw_tsfm:complete.ts=%u\n", os_boot_time32());
|
|
}
|
|
|
|
static uint8_t IRAM_ATTR mac_hw_tsfm_timer_isr_handle(iot_addrword_t data)
|
|
{
|
|
uint8_t byte_idx, bit_idx;
|
|
uint32_t cur_ts = iot_gp_timer_get_curr_ts();
|
|
uint32_t delta;
|
|
mac_hw_tsfm_ctxt_t *tsfm = (mac_hw_tsfm_ctxt_t *)data;
|
|
IOT_ASSERT(tsfm);
|
|
|
|
if (0 == tsfm->tsfm_mode) {
|
|
return 0;
|
|
}
|
|
|
|
if (tsfm->status.encode_idx < tsfm->config.bit_len) {
|
|
byte_idx = tsfm->status.encode_idx >> 3;
|
|
bit_idx = tsfm->status.encode_idx & 0x07;
|
|
|
|
delta = cur_ts - tsfm->status.encode_ts;
|
|
if (tsfm->config.data[byte_idx] & (1 << (7 - bit_idx))) {
|
|
/* encode logic 1 */
|
|
if (delta >= (tsfm->status.is_encode_tx
|
|
? MAC_HW_TSFM_ENCODE_TX_US : MAC_HW_TSFM_ENCODE_IDLE_US)) {
|
|
tsfm->status.encode_ts = cur_ts;
|
|
tsfm->status.is_encode_tx = !tsfm->status.is_encode_tx;
|
|
}
|
|
} else {
|
|
/* encode logic 0 */
|
|
tsfm->status.is_encode_tx = 0;
|
|
}
|
|
|
|
delta = cur_ts - tsfm->status.tsfm_bit_ts;
|
|
if (delta >= MAC_HW_TSFM_PER_BIT_DUR_US) {
|
|
tsfm->status.tsfm_bit_ts = cur_ts;
|
|
tsfm->status.encode_idx++;
|
|
|
|
if (tsfm->status.encode_idx >= tsfm->config.bit_len) {
|
|
tsfm->status.is_encode_tx = 0;
|
|
tsfm->tsfm_mode = 0;
|
|
/* set mac dsr */
|
|
if (p_mac_glb->task_h) {
|
|
os_set_task_event_with_v_from_isr(p_mac_glb->task_h,
|
|
(uint32_t)(0x1 << MAC_DSR_HW_TSFM_COMPLETE_ID));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (tsfm->status.is_encode_tx) {
|
|
mac_hw_tsfm_signal_tx(tsfm->config.encode_tone_num);
|
|
} else {
|
|
mac_hw_tsfm_signal_idle();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static uint32_t mac_hw_tsfm_get_duration_time(mac_hw_tsfm_ctxt_t *tsfm)
|
|
{
|
|
/* us to ms */
|
|
return tsfm ? iot_ceil(MAC_HW_TSFM_PER_BIT_DUR_US * tsfm->config.bit_len,
|
|
1000) : 0;
|
|
}
|
|
|
|
static uint32_t mac_hw_tsfm_start(mac_hw_tsfm_ctxt_t *tsfm)
|
|
{
|
|
uint32_t dur_time;
|
|
mac_pdev_t *pdev;
|
|
|
|
if (!tsfm) {
|
|
return 0;
|
|
}
|
|
iot_gp_timer_stop(tsfm->timer_id);
|
|
|
|
tsfm->tsfm_mode = 1;
|
|
|
|
/* clear event */
|
|
mac_dsr_clear(MAC_DSR_HW_TSFM_COMPLETE_ID);
|
|
|
|
/* backup ada config */
|
|
tsfm->backup.ada_eb = ahb_ada_is_enable();
|
|
tsfm->backup.ada_power_on = phy_ada_get_power_on();
|
|
|
|
/* ada clk enable */
|
|
enable_ada(1);
|
|
/* ada power on */
|
|
phy_ada_enable(1);
|
|
|
|
phy_reset(PHY_RST_REASON_COLD);
|
|
|
|
/* pm init wake up */
|
|
mac_pm_init_wake_up();
|
|
/* disable check spur */
|
|
pdev = get_pdev_ptr(tsfm->ref_pdev_id);
|
|
IOT_ASSERT(pdev);
|
|
mac_check_spur_en(&pdev->mac_check_spur_ctxt, 0);
|
|
|
|
tsfm->backup.tx_rate_mode_ovr = phy_tx_rate_mode_ovr_get();
|
|
phy_tx_rate_mode_ovr_set(1, MAC_HW_TSFM_ENCODE_RATE_MODE);
|
|
|
|
/* force tx */
|
|
phy_set_tx_force_enable(1);
|
|
|
|
/* enable analog tx */
|
|
phy_ana_i2c_write(CFG_ANA_TOP_REG_ADDR,
|
|
TOP_EN_TX_MASK | TOP_EN_DAC_MASK | (2 << TOP_ENLIC_OFFSET),
|
|
TOP_EN_TX_MASK | TOP_EN_DAC_MASK | TOP_ENLIC_MASK);
|
|
|
|
/* atten control */
|
|
phy_dfe_tone_att_cfg(0, 1, 0);
|
|
|
|
/* fix tx power and backup */
|
|
tsfm->backup.ana_pga_gain = phy_ana_pga_gain_get();
|
|
tsfm->backup.tx_pwr_scale_factor = phy_tx_gain_factor_get();
|
|
phy_ana_pga_gain_set(3);
|
|
phy_tx_gain_factor_set(PHY_PWR_DIG_ATT_MAX);
|
|
|
|
/* set current status */
|
|
tsfm->status.encode_idx = 0;
|
|
tsfm->status.is_encode_tx = 1;
|
|
tsfm->status.encode_ts = iot_gp_timer_get_curr_ts();
|
|
tsfm->status.tsfm_bit_ts = tsfm->status.encode_ts;
|
|
if (tsfm->config.data[0] & (1 << 7)) {
|
|
mac_hw_tsfm_signal_tx(tsfm->config.encode_tone_num);
|
|
tsfm->status.is_encode_tx = 1;
|
|
} else {
|
|
mac_hw_tsfm_signal_idle();
|
|
tsfm->status.is_encode_tx = 0;
|
|
}
|
|
|
|
//start gp timer
|
|
dur_time = mac_hw_tsfm_get_duration_time(tsfm);
|
|
iot_gp_timer_set(tsfm->timer_id, MAC_HW_TSFM_ENCODE_TIMER_US, 1);
|
|
iot_gp_timer_start(tsfm->timer_id);
|
|
iot_printf("mac_hw_tsfm:start.freq=%uHZ, ts=%u, dur=%u\n",
|
|
mac_hw_tsfm_tonenum_to_freq(tsfm->config.encode_tone_num),
|
|
os_boot_time32(), dur_time);
|
|
|
|
mac_hw_tsfm_dbg_print("mac_hw_tsfm:config. timer_peroid=%u, "
|
|
"tx=%u, idle=%u, bit_dur=%u, rate_mode=%u\n",
|
|
MAC_HW_TSFM_ENCODE_TIMER_US,
|
|
MAC_HW_TSFM_ENCODE_TX_US,
|
|
MAC_HW_TSFM_ENCODE_IDLE_US,
|
|
MAC_HW_TSFM_PER_BIT_DUR_US,
|
|
MAC_HW_TSFM_ENCODE_RATE_MODE);
|
|
|
|
mac_hw_tsfm_dbg_print("mac_hw_tsfm:backup.tx_mode=%d, ada-%d:%d, "
|
|
"pga=%d, tx_scale=%d\n",
|
|
tsfm->backup.tx_rate_mode_ovr,
|
|
tsfm->backup.ada_eb,
|
|
tsfm->backup.ada_power_on,
|
|
tsfm->backup.ana_pga_gain,
|
|
tsfm->backup.tx_pwr_scale_factor);
|
|
|
|
return dur_time;
|
|
}
|
|
|
|
void mac_hw_tsfm_init(uint8_t fw_mode, uint8_t pdev_id)
|
|
{
|
|
uint32_t err_no;
|
|
mac_pdev_t *pdev;
|
|
mac_hw_tsfm_ctxt_t *tsfm;
|
|
|
|
if ((MM_MODE != fw_mode) || (PLC_PDEV_ID != pdev_id)) {
|
|
return;
|
|
}
|
|
|
|
do {
|
|
/* get pdev context */
|
|
pdev = get_pdev_ptr(pdev_id);
|
|
if (NULL == pdev) {
|
|
err_no = __LINE__;
|
|
break;
|
|
}
|
|
|
|
/* alloc codec context */
|
|
tsfm = os_mem_malloc(PLC_MAC_COMMON_MID, sizeof(*tsfm));
|
|
if (NULL == tsfm) {
|
|
err_no = __LINE__;
|
|
break;
|
|
}
|
|
|
|
/* create timer */
|
|
tsfm->timer_id = iot_gp_timer_create(0, NULL,
|
|
mac_hw_tsfm_timer_isr_handle, (iot_addrword_t)tsfm);
|
|
if (!mac_hw_tsfm_timer_is_valid(tsfm->timer_id)) {
|
|
err_no = __LINE__;
|
|
break;
|
|
}
|
|
|
|
mac_dsr_set_entry(&p_mac_glb->dsr_table, MAC_DSR_HW_TSFM_COMPLETE_ID,
|
|
mac_hw_tsfm_complete);
|
|
|
|
/* success */
|
|
err_no = 0;
|
|
pdev->hw_tsfm = tsfm;
|
|
tsfm->tsfm_mode = 0;
|
|
tsfm->ref_pdev_id = pdev_id;
|
|
} while(0);
|
|
|
|
iot_printf("mac_hw_tsfm:init %d\n", err_no);
|
|
IOT_ASSERT_DUMP(!err_no, &err_no, 1);
|
|
}
|
|
|
|
uint32_t mac_hw_tsfm_send_internal(pdevid_t pdev_id, vdevid_t vdev_id,
|
|
mac_hw_tsfm_tx_info_t *tx_info)
|
|
{
|
|
uint8_t i, byte_len;
|
|
uint32_t err_no;
|
|
uint32_t dur_time;
|
|
mac_pdev_t *pdev;
|
|
mac_vdev_t *vdev;
|
|
mac_hw_tsfm_ctxt_t *tsfm;
|
|
|
|
byte_len = iot_ceil(tx_info->bit_len, 8);
|
|
|
|
iot_printf("mac_hw_tsfm:tx para.id:%d-%d.freq:%dHz,bit_len=%d.[",
|
|
pdev_id, vdev_id, tx_info->freq_tone_num, tx_info->bit_len);
|
|
if (tx_info) {
|
|
for (i = 0; i < byte_len; i++) {
|
|
iot_printf(" 0x%02x", tx_info->data[i]);
|
|
}
|
|
iot_printf("]\n");
|
|
}
|
|
|
|
do {
|
|
pdev = get_pdev_ptr(pdev_id);
|
|
if ((PLC_PDEV_ID != pdev_id) || (byte_len > MAC_HW_TSFM_DATA_BYTE_MAX)
|
|
|| !tx_info || !pdev) {
|
|
err_no = __LINE__;
|
|
break;
|
|
}
|
|
|
|
tsfm = (mac_hw_tsfm_ctxt_t *)pdev->hw_tsfm;
|
|
if (NULL == tsfm) {
|
|
err_no = __LINE__;
|
|
break;
|
|
}
|
|
|
|
/* record receieve tx request count */
|
|
tsfm->logger.tx_req_cnt++;
|
|
|
|
vdev = get_vdev_ptr(pdev_id, vdev_id);
|
|
if ((PLC_DEFAULT_VDEV != vdev_id) || !vdev) {
|
|
err_no = __LINE__;
|
|
break;
|
|
}
|
|
|
|
if (tsfm->tsfm_mode) {
|
|
err_no = __LINE__;
|
|
break;
|
|
}
|
|
|
|
err_no = 0;
|
|
} while (0);
|
|
|
|
if (0 == err_no) {
|
|
tsfm->config.bit_len = tx_info->bit_len;
|
|
tsfm->config.encode_tone_num = tx_info->freq_tone_num;
|
|
os_mem_cpy(tsfm->config.data, tx_info->data, byte_len);
|
|
|
|
if (vdev->is_up) {
|
|
mac_stop_vdev_internal(pdev_id, vdev_id);
|
|
}
|
|
dur_time = mac_hw_tsfm_start(tsfm);
|
|
} else {
|
|
iot_printf("mac_hw_tsfm: send err %u\n", err_no);
|
|
dur_time = 0;
|
|
}
|
|
|
|
return dur_time;
|
|
}
|
|
|
|
uint32_t mac_hw_tsfm_send(pdevid_t pdev_id, vdevid_t vdev_id,
|
|
mac_hw_tsfm_tx_info_t *tx_info)
|
|
{
|
|
uint32_t ret;
|
|
mac_msg_sync_t *msg = mac_alloc_msg_sync();
|
|
|
|
if (msg == NULL) {
|
|
IOT_ASSERT(0);
|
|
return ERR_NOMEM;
|
|
}
|
|
|
|
msg->msg.type = MAC_MSG_TYPE_CVG;
|
|
msg->msg.id = MAC_MSG_ID_CVG_HW_TSFM_SEND;
|
|
msg->msg.data1 = (((uint32_t)pdev_id) << 8) | vdev_id;
|
|
msg->msg.data2 = (void *)tx_info;
|
|
mac_queue_msg_sync(msg, MAC_MSG_QUEUE_HP);
|
|
ret = msg->msg.data1;
|
|
|
|
mac_free_msg_sync(msg);
|
|
|
|
return ret;
|
|
}
|
|
|
|
#else //PLC_SUPPORT_HW_TSFM_PA
|
|
|
|
uint32_t mac_hw_tsfm_send_internal(pdevid_t pdev_id, vdevid_t vdev_id,
|
|
mac_hw_tsfm_tx_info_t *tx_info)
|
|
{
|
|
(void)pdev_id;
|
|
(void)vdev_id;
|
|
(void)tx_info;
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t mac_hw_tsfm_send(pdevid_t pdev_id, vdevid_t vdev_id,
|
|
mac_hw_tsfm_tx_info_t *tx_info)
|
|
{
|
|
(void)pdev_id;
|
|
(void)vdev_id;
|
|
(void)tx_info;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void mac_hw_tsfm_init(uint8_t fw_mode, uint8_t pdev_id)
|
|
{
|
|
(void)fw_mode;
|
|
(void)pdev_id;
|
|
return;
|
|
}
|
|
|
|
#endif //PLC_SUPPORT_HW_TSFM_PA
|