634 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			634 lines
		
	
	
		
			17 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 "mac_pm.h"
 | 
						|
#include "mac_msg.h"
 | 
						|
#include "mac.h"
 | 
						|
#include "mac_vdev.h"
 | 
						|
#include "mac_pdev.h"
 | 
						|
#include "mac_sched.h"
 | 
						|
#include "mac_sched_hw.h"
 | 
						|
#include "mac_tx_hw.h"
 | 
						|
#include "iot_io.h"
 | 
						|
#include "iot_clock.h"
 | 
						|
#include "clk.h"
 | 
						|
#include "cpu.h"
 | 
						|
#include "ahb.h"
 | 
						|
#include "phy_chn.h"
 | 
						|
#include "phy_rf_chn.h"
 | 
						|
#include "hw_phy_api.h"
 | 
						|
#include "mac_init_api.h"
 | 
						|
#include "mac_tx_power.h"
 | 
						|
#include "mac_reset.h"
 | 
						|
#include "iot_board.h"
 | 
						|
#include "iot_oem_api.h"
 | 
						|
#include "phy_rf_init.h"
 | 
						|
#include "mac_rf_tx_power.h"
 | 
						|
#include "os_utils_api.h"
 | 
						|
 | 
						|
#if PM_USE_DSR
 | 
						|
extern mac_pdev_t* g_mac_pdev[MAX_PDEV_NUM];
 | 
						|
extern mac_global_t* p_mac_glb;
 | 
						|
#endif
 | 
						|
 | 
						|
typedef void (*mac_pm_switch_freq_cb_t)();
 | 
						|
 | 
						|
/* callback for mac pm switch freq function */
 | 
						|
mac_pm_switch_freq_cb_t mac_pm_switch_freq_cb = NULL;
 | 
						|
 | 
						|
void register_mac_pm_switch_freq_cb(mac_pm_switch_freq_cb_t cb)
 | 
						|
{
 | 
						|
#if (PLC_PM_SWITCH_POLICY == 1)
 | 
						|
    mac_pm_switch_freq_cb = cb;
 | 
						|
#endif
 | 
						|
    (void)cb;
 | 
						|
}
 | 
						|
 | 
						|
void mac_pm_check_freq()
 | 
						|
{
 | 
						|
    if (mac_pm_switch_freq_cb) {
 | 
						|
        mac_pm_switch_freq_cb();
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t mac_pm_get_band_sleep_intvl(uint32_t proto, \
 | 
						|
    uint32_t proto_bandid)
 | 
						|
{
 | 
						|
    uint8_t sg_band_sleep_table_ms[MAX_SG_BAND_ID] = {
 | 
						|
            20, // band 0
 | 
						|
            25, // band 1
 | 
						|
            40, // band 2
 | 
						|
            60, // band 3
 | 
						|
            20, // band 4
 | 
						|
            0,  // band 5
 | 
						|
            0,  // band 6
 | 
						|
            0,  // band 7
 | 
						|
            20, // band 8
 | 
						|
            20, // band 9
 | 
						|
            20, // band 10
 | 
						|
            20  // band 11
 | 
						|
    };
 | 
						|
    if (proto == PLC_PROTO_TYPE_SG) {
 | 
						|
        if (proto_bandid < MAX_SG_BAND_ID) {
 | 
						|
            return sg_band_sleep_table_ms[proto_bandid];
 | 
						|
        } else {
 | 
						|
            return sg_band_sleep_table_ms[MAX_SG_BAND_ID - 1];
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else if(proto == PLC_PROTO_TYPE_SPG) {
 | 
						|
        if (proto_bandid < MAX_SG_BAND_ID) {
 | 
						|
            return sg_band_sleep_table_ms[proto_bandid];
 | 
						|
        } else {
 | 
						|
            return sg_band_sleep_table_ms[MAX_SG_BAND_ID - 1];
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else if (proto == PLC_PROTO_TYPE_GP) {
 | 
						|
        return 3;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        return 20;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void deep_sleep_wake_up(uint32_t freq)
 | 
						|
{
 | 
						|
#if (PLC_PM_SWITCH_POLICY == 0)
 | 
						|
    /* change the clock to PLL */
 | 
						|
    system_cpu_wakeup(1, freq);
 | 
						|
#endif
 | 
						|
    /* phy enter normal mode */
 | 
						|
    phy_idle_clr();
 | 
						|
}
 | 
						|
 | 
						|
void mac_pm_init_wake_up()
 | 
						|
{
 | 
						|
    /* requst mac pm stay awake */
 | 
						|
    req_stay_awake(MAC_PM_INIT_MODULE_ID, 1);
 | 
						|
#if STATIC_POWER_SAVE
 | 
						|
#if (PLC_PM_SWITCH_POLICY == 1)
 | 
						|
    /* change the clock to PLL */
 | 
						|
    system_cpu_wakeup(1, CPU_FREQ_150M);
 | 
						|
#endif
 | 
						|
    deep_sleep_wake_up(CPU_FREQ_150M);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t wake_up(uint8_t sleep_level)
 | 
						|
{
 | 
						|
    mac_pdev_t *pdev = (mac_pdev_t *)g_mac_pdev[PLC_PDEV_ID];
 | 
						|
 | 
						|
    if (sleep_level == DEEP_SLEEP_LEVEL_1) {
 | 
						|
        deep_sleep_wake_up(CPU_FREQ_75M);
 | 
						|
        pdev->mac_pm.cur_status = WAKE_UP;
 | 
						|
    } else if (sleep_level == DEEP_SLEEP_LEVEL_2) {
 | 
						|
        deep_sleep_wake_up(CPU_FREQ_150M);
 | 
						|
        pdev->mac_pm.cur_status = WAKE_UP;
 | 
						|
    }
 | 
						|
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t mac_pm_war_function(mac_pdev_t *pdev)
 | 
						|
{
 | 
						|
    if (pdev == NULL) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
 | 
						|
#if WAR_FOR_LOW_POWER
 | 
						|
 | 
						|
    /* once the phy txrxn state has been entered, this war is not enabled */
 | 
						|
    if (g_phy_ctxt.dep.raise_dcdccode_flag) {
 | 
						|
        pdev->mac_pm.pm_war_state = 0;
 | 
						|
        goto next;
 | 
						|
    }
 | 
						|
 | 
						|
#define MAC_PM_WAR_PERIOD_1200MS       2500
 | 
						|
#define MAC_PM_WAR_PERIOD_19800MS      18500
 | 
						|
 | 
						|
    uint32_t dlt = os_boot_time32() - pdev->mac_pm.mac_pm_anchor_ts;
 | 
						|
    if (pdev->mac_pm.pm_war_state) {
 | 
						|
        if (dlt >= MAC_PM_WAR_PERIOD_1200MS) {
 | 
						|
            pdev->mac_pm.pm_war_state = 0;
 | 
						|
            pdev->mac_pm.mac_pm_anchor_ts = os_boot_time32();
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        if (dlt >= MAC_PM_WAR_PERIOD_19800MS) {
 | 
						|
            pdev->mac_pm.pm_war_state = 1;
 | 
						|
            pdev->mac_pm.mac_pm_anchor_ts = os_boot_time32();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
next:
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
    return pdev->mac_pm.pm_war_state;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t mac_pm_sleep_wakeup(mac_pdev_t *pdev)
 | 
						|
{
 | 
						|
    if (NULL == pdev) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        return ERR_INVAL;
 | 
						|
    }
 | 
						|
 | 
						|
    /* make sure timer is on */
 | 
						|
    if (!pdev->mac_pm.is_start) {
 | 
						|
        if (pdev->mac_pm.sleep_timer) {
 | 
						|
            os_stop_timer(pdev->mac_pm.sleep_timer);
 | 
						|
        }
 | 
						|
        /* wake up */
 | 
						|
        if (pdev->mac_pm.cur_status == DEEP_SLEEP) {
 | 
						|
            wake_up(DEEP_SLEEP_LEVEL_2);
 | 
						|
        }
 | 
						|
        /* rf wake up */
 | 
						|
        phy_rf_set_ps_idle(0);
 | 
						|
 | 
						|
        pdev->mac_pm.is_sleep_wakeup_valid = 0;
 | 
						|
 | 
						|
        return ERR_INVAL;
 | 
						|
    }
 | 
						|
 | 
						|
    pdev->mac_pm.wake_time_ms = mac_pm_get_band_sleep_intvl(
 | 
						|
            PHY_PROTO_TYPE_GET(),
 | 
						|
            phy_band_id_get());
 | 
						|
    pdev->mac_pm.sleep_time_ms = 2 * pdev->mac_pm.wake_time_ms;
 | 
						|
 | 
						|
    mac_pm_war_function(pdev);
 | 
						|
 | 
						|
    switch (pdev->mac_pm.cur_status) {
 | 
						|
    case WAKE_UP:
 | 
						|
        if (g_phy_cpu_share_ctxt.pm_status.bitmap == 0) {
 | 
						|
            sleep(DEEP_SLEEP_LEVEL_1);
 | 
						|
            if (!pdev->mac_pm.pm_war_state) {
 | 
						|
                /* rf wakeup */
 | 
						|
                phy_rf_set_ps_idle(0);
 | 
						|
            }
 | 
						|
            os_stop_timer(pdev->mac_pm.sleep_timer);
 | 
						|
            os_start_timer(pdev->mac_pm.sleep_timer,
 | 
						|
                pdev->mac_pm.sleep_time_ms);
 | 
						|
        } else if (pdev->mac_pm.fc_ok_pm &&
 | 
						|
            g_phy_cpu_share_ctxt.pm_status.fc_ok_found) {
 | 
						|
            phy_pkt_found_flag_clr();
 | 
						|
            os_stop_timer(pdev->mac_pm.sleep_timer);
 | 
						|
            os_start_timer(pdev->mac_pm.sleep_timer, pdev->mac_pm.wake_time_ms);
 | 
						|
        } else {
 | 
						|
            /* rf wake up */
 | 
						|
            phy_rf_set_ps_idle(0);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    case DEEP_SLEEP:
 | 
						|
        /* rf sleep */
 | 
						|
        phy_rf_set_ps_idle(1);
 | 
						|
        wake_up(DEEP_SLEEP_LEVEL_1);
 | 
						|
        os_stop_timer(pdev->mac_pm.sleep_timer);
 | 
						|
        os_start_timer(pdev->mac_pm.sleep_timer, pdev->mac_pm.wake_time_ms);
 | 
						|
        break;
 | 
						|
    default:
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
 | 
						|
    pdev->mac_pm.is_sleep_wakeup_valid = 0;
 | 
						|
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
void mac_pm_rx_power_off(uint32_t arg, uint32_t data)
 | 
						|
{
 | 
						|
    iot_printf("%s\n", __FUNCTION__);
 | 
						|
 | 
						|
    mac_msg_t *msg = mac_alloc_msg();
 | 
						|
 | 
						|
    (void)data;
 | 
						|
    if (msg == NULL) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    msg->type = MAC_MSG_TYPE_PM;
 | 
						|
    msg->id = MAC_MSG_ID_PM_OFF;
 | 
						|
    msg->data1 = arg;
 | 
						|
    mac_queue_msg(msg, MAC_MSG_QUEUE_HP);
 | 
						|
out:
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t mac_pm_rx_power_off_internal(uint8_t pdev_id, uint8_t vdev_id)
 | 
						|
{
 | 
						|
    mac_vdev_t * vdev = get_vdev_ptr(pdev_id, vdev_id);
 | 
						|
    mac_pdev_t *pdev_ptr = (mac_pdev_t *)g_mac_pdev[pdev_id];
 | 
						|
 | 
						|
    if (vdev == NULL) {
 | 
						|
        return ERR_INVAL;
 | 
						|
    }
 | 
						|
 | 
						|
    iot_printf("%s, pdevid=%d, dbgvdevid:%d, vdevid = %d\n",
 | 
						|
        __FUNCTION__, pdev_id, pdev_ptr->dbg_pkt_vdev_id, vdev_id);
 | 
						|
 | 
						|
    if (vdev->is_up == 0) {
 | 
						|
        return ERR_OK;
 | 
						|
    }
 | 
						|
 | 
						|
    if (pdev_ptr->dbg_pkt_vdev_id == vdev->vdev_id) {
 | 
						|
        return ERR_OK;
 | 
						|
    }
 | 
						|
 | 
						|
    pdev_ptr->mac_pm.mac_pm_flag = 1;   //flag for power off
 | 
						|
    if (pdev_ptr->mac_pm.pwroff_timer &&
 | 
						|
        pdev_ptr->mac_pm.power_off_high_power) {
 | 
						|
        os_start_timer(pdev_ptr->mac_pm.pwroff_timer, MAC_HP_FOR_PWROFF);
 | 
						|
    }
 | 
						|
 | 
						|
    /* set high pwr for pwroff */
 | 
						|
    mac_high_power_req_ena(vdev, false);
 | 
						|
 | 
						|
    if (pdev_ptr->mac_pm.power_off_high_power) {
 | 
						|
        uint8_t hplc_power = PHY_FULL_PWR_DBUV;
 | 
						|
        int8_t rf_power = RF_TX_PWR_INVALID;
 | 
						|
        phy_rf_get_power(NULL, NULL, NULL, &rf_power);
 | 
						|
        mac_set_tx_power_cap(vdev, &hplc_power, &rf_power, 1);
 | 
						|
    } else {
 | 
						|
        uint8_t hplc_power = 0;
 | 
						|
        int8_t rf_power = RF_TX_PWR_INVALID;
 | 
						|
        mac_set_tx_power_cap(vdev, &hplc_power, &rf_power, 1);
 | 
						|
    }
 | 
						|
 | 
						|
    /* CCO does not process power off handle */
 | 
						|
    if (mac_vdev_cfg_get_node_role(vdev) == PLC_DEV_ROLE_CCO) {
 | 
						|
        return ERR_OK;
 | 
						|
    }
 | 
						|
 | 
						|
#if DEBUG_HWQ_SHCED_HANG
 | 
						|
    pdev_ptr->dbg_status = MAC_TX_HANG_STATUS_3;
 | 
						|
#endif
 | 
						|
 | 
						|
    /* clear tx packet in hw queue */
 | 
						|
    mac_pre_phy_reinit();
 | 
						|
 | 
						|
#if DEBUG_HWQ_SHCED_HANG
 | 
						|
    pdev_ptr->dbg_status = MACC_TX_HANG_STATUS_MAX;
 | 
						|
#endif
 | 
						|
 | 
						|
    /* restart and enable tx */
 | 
						|
    mac_post_phy_reinit(1);
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t mac_pm_power_recover_internal(uint8_t pdev_id, uint8_t vdev_id)
 | 
						|
{
 | 
						|
 | 
						|
    mac_vdev_t * vdev = get_vdev_ptr(pdev_id, vdev_id);
 | 
						|
    mac_pdev_t *pdev_ptr = (mac_pdev_t *)g_mac_pdev[pdev_id];
 | 
						|
 | 
						|
    if (vdev == NULL) {
 | 
						|
        return ERR_INVAL;
 | 
						|
    }
 | 
						|
 | 
						|
    iot_printf("%s, pdevid=%d, dbgvdevid:%d, vdevid = %d\n",
 | 
						|
        __FUNCTION__, pdev_id, pdev_ptr->dbg_pkt_vdev_id, vdev_id);
 | 
						|
 | 
						|
    if (vdev->is_up == 0) {
 | 
						|
        return ERR_OK;
 | 
						|
    }
 | 
						|
 | 
						|
    if (pdev_ptr->dbg_pkt_vdev_id == vdev->vdev_id) {
 | 
						|
        return ERR_OK;
 | 
						|
    }
 | 
						|
 | 
						|
    pdev_ptr->mac_pm.mac_pm_flag = 0;   //flag for power recover
 | 
						|
 | 
						|
    if (pdev_ptr->mac_pm.pwroff_timer) {
 | 
						|
        os_stop_timer(pdev_ptr->mac_pm.pwroff_timer);
 | 
						|
    }
 | 
						|
 | 
						|
#if DEBUG_HWQ_SHCED_HANG
 | 
						|
    pdev_ptr->dbg_status = MAC_TX_HANG_STATUS_5;
 | 
						|
#endif
 | 
						|
 | 
						|
    /* clear tx packet in hw queue */
 | 
						|
    mac_pre_phy_reinit();
 | 
						|
 | 
						|
#if DEBUG_HWQ_SHCED_HANG
 | 
						|
    pdev_ptr->dbg_status = MACC_TX_HANG_STATUS_MAX;
 | 
						|
#endif
 | 
						|
 | 
						|
    mac_fix_power_apply(vdev);
 | 
						|
 | 
						|
    /* restart and disable tx */
 | 
						|
    mac_post_phy_reinit(0);
 | 
						|
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
void sleep_cfg(timer_id_t timer_id, void * arg)
 | 
						|
{
 | 
						|
#if PM_USE_DSR
 | 
						|
    (void)timer_id;
 | 
						|
    (void)arg;
 | 
						|
    os_set_task_event_with_v(p_mac_glb->task_h, \
 | 
						|
        1 << MAC_DSR_POWER_PM_ID);
 | 
						|
#else
 | 
						|
    mac_pdev_t *pdev = (mac_pdev_t*)arg;
 | 
						|
 | 
						|
    (void) timer_id;
 | 
						|
    if (!pdev->mac_pm.is_sleep_wakeup_valid) {
 | 
						|
        /* timer context */
 | 
						|
        mac_msg_t *msg = mac_alloc_msg();
 | 
						|
 | 
						|
        if (msg == NULL) {
 | 
						|
            IOT_ASSERT(0);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        pdev->mac_pm.is_sleep_wakeup_valid = 1;
 | 
						|
        msg->type = MAC_MSG_TYPE_TIMER;
 | 
						|
        msg->id = MAC_MSG_ID_SYSTEM_SLEEP;
 | 
						|
        msg->data1 = 0;
 | 
						|
        msg->data2 = arg;
 | 
						|
        mac_queue_msg(msg, MAC_MSG_QUEUE_MP);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void mac_pm_switch_freq()
 | 
						|
{
 | 
						|
#if (PLC_PM_SWITCH_POLICY == 1)
 | 
						|
    mac_pdev_t *pdev = get_pdev_ptr(PLC_PDEV_ID);
 | 
						|
    if (pdev->mac_pm.is_check_freq && cpu_get_clock() != CPU_FREQ_150M) {
 | 
						|
        pdev->mac_pm.is_check_freq = 0;
 | 
						|
        /* change the clock to 150M */
 | 
						|
        system_cpu_wakeup(1, CPU_FREQ_150M);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
uint32_t mac_pm_init(void *pdev_in)
 | 
						|
{
 | 
						|
    mac_pdev_t *pdev = (mac_pdev_t*) pdev_in;
 | 
						|
 | 
						|
#if STATIC_POWER_SAVE
 | 
						|
    pdev->mac_pm.wake_time_ms = mac_pm_get_band_sleep_intvl(
 | 
						|
            PHY_PROTO_TYPE_GET(),
 | 
						|
            phy_proto_single_band_id_get());
 | 
						|
    pdev->mac_pm.sleep_time_ms = 2 * pdev->mac_pm.wake_time_ms;
 | 
						|
    pdev->mac_pm.cur_status = WAKE_UP; //cur status wake up
 | 
						|
    pdev->mac_pm.is_sleep_wakeup_valid = 0;
 | 
						|
    pdev->mac_pm.is_start = 0;
 | 
						|
    /* init awake reason, except for reason MAC_PM_CERT_TEST_MODULE_ID */
 | 
						|
    phy_pkt_found_flag_clr();
 | 
						|
    g_phy_cpu_share_ctxt.pm_status.band_select_ok = 0;
 | 
						|
    req_stay_awake(MAC_PM_INIT_MODULE_ID, false);
 | 
						|
    req_stay_awake(MAC_PM_SCAN_MODULE_ID, false);
 | 
						|
    if (pdev->mac_pm.sleep_timer == 0) {
 | 
						|
        pdev->mac_pm.sleep_timer = os_create_timer(PLC_MAC_STATUSE_MID, false,
 | 
						|
                    sleep_cfg, pdev);
 | 
						|
        /* record mac pm start ts */
 | 
						|
        pdev->mac_pm.mac_pm_anchor_ts = os_boot_time32();
 | 
						|
        pdev->mac_pm.pm_war_state = 0;
 | 
						|
    }
 | 
						|
    /* enable brg async */
 | 
						|
    ahb_rf_brg_async();
 | 
						|
    register_mac_pm_switch_freq_cb(mac_pm_switch_freq);
 | 
						|
#endif
 | 
						|
    if (pdev->mac_pm.pwroff_timer == 0) {
 | 
						|
        pdev->mac_pm.pwroff_timer = os_create_timer(PLC_MAC_STATUSE_MID, \
 | 
						|
            false, low_pwr_for_powroff_cfg, pdev);
 | 
						|
    }
 | 
						|
    /* power off high power */
 | 
						|
    uint32_t hw_ver = iot_board_hw_version_hex();
 | 
						|
    if (HW_VERSION_GS_NO_IPD_STA != hw_ver &&
 | 
						|
        HW_VERSION_GS_NO_IPD_STA_3P != hw_ver) {
 | 
						|
        pdev->mac_pm.power_off_high_power = 1;
 | 
						|
    } else {
 | 
						|
        pdev->mac_pm.power_off_high_power = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t mac_pm_start(void *pdev_in)
 | 
						|
{
 | 
						|
    IOT_ASSERT(pdev_in);
 | 
						|
    mac_pdev_t *pdev = (mac_pdev_t*) pdev_in;
 | 
						|
    if (pdev->mac_pm.sleep_timer) {
 | 
						|
        phy_pkt_found_flag_clr();
 | 
						|
        os_start_timer(pdev->mac_pm.sleep_timer, pdev->mac_pm.sleep_time_ms);
 | 
						|
        pdev->mac_pm.is_start = 1;
 | 
						|
        pdev->mac_pm.is_check_freq = 0;
 | 
						|
#if (PLC_PM_SWITCH_POLICY == 1)
 | 
						|
        system_cpu_sleep(1);
 | 
						|
#endif
 | 
						|
    } else {
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t mac_pm_stop(void *pdev_in)
 | 
						|
{
 | 
						|
    IOT_ASSERT(pdev_in);
 | 
						|
    mac_pdev_t *pdev = (mac_pdev_t*) pdev_in;
 | 
						|
 | 
						|
    if (pdev->mac_pm.sleep_timer) {
 | 
						|
        if (pdev->mac_pm.cur_status == DEEP_SLEEP) {
 | 
						|
            wake_up(DEEP_SLEEP_LEVEL_2);
 | 
						|
        }
 | 
						|
        /* rf wake up */
 | 
						|
        phy_rf_set_ps_idle(0);
 | 
						|
        os_stop_timer(pdev->mac_pm.sleep_timer);
 | 
						|
        pdev->mac_pm.is_start = 0;
 | 
						|
        pdev->mac_pm.is_check_freq = 1;
 | 
						|
    } else {
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
void deep_sleep()
 | 
						|
{
 | 
						|
    /* phy and analog enter IDLE */
 | 
						|
    phy_idle_set();
 | 
						|
#if (IOT_SMART_GRID_ENABLE && HW_PLATFORM >= HW_PLATFORM_FPGA)
 | 
						|
    if (cpu_get_clock() != CPU_FREQ_25M) {
 | 
						|
        /* change the clock to 25M */
 | 
						|
        system_cpu_sleep(1);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
uint32_t sleep(uint8_t sleep_level)
 | 
						|
{
 | 
						|
    mac_pdev_t *pdev = (mac_pdev_t *)g_mac_pdev[PLC_PDEV_ID];
 | 
						|
 | 
						|
    if (sleep_level == DEEP_SLEEP_LEVEL_1) {
 | 
						|
        deep_sleep();
 | 
						|
        pdev->mac_pm.cur_status = DEEP_SLEEP;
 | 
						|
    }
 | 
						|
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t req_stay_awake(uint32_t module_bit, uint32_t req_awake)
 | 
						|
{
 | 
						|
    if (req_awake) {
 | 
						|
        g_phy_cpu_share_ctxt.pm_status.bitmap |= module_bit;
 | 
						|
    } else {
 | 
						|
        g_phy_cpu_share_ctxt.pm_status.bitmap &= ~module_bit;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
#if PM_USE_DSR
 | 
						|
void mac_pm_dsr_sleep_cfg(void)
 | 
						|
{
 | 
						|
    mac_pdev_t *pdev = (mac_pdev_t *)g_mac_pdev[PLC_PDEV_ID];
 | 
						|
 | 
						|
    /* because the dsr event handle maybe delay for some long time task,
 | 
						|
     * for example vdev_stop, the pm timer handler may be handled after
 | 
						|
     * timer stopped, to avoid this, we introduced this flag.
 | 
						|
     */
 | 
						|
    if (pdev->mac_pm.is_start == 1) {
 | 
						|
        mac_pm_sleep_wakeup(g_mac_pdev[PLC_PDEV_ID]);
 | 
						|
    }
 | 
						|
}
 | 
						|
#else
 | 
						|
uint32_t sleep_cfg_internal(void *arg)
 | 
						|
{
 | 
						|
    return mac_pm_sleep_wakeup((mac_pdev_t*)arg);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
void low_pwr_for_powroff_cfg(timer_id_t timer_id, void * arg)
 | 
						|
{
 | 
						|
    iot_printf("%s\n", __FUNCTION__);
 | 
						|
 | 
						|
    mac_msg_t *msg = mac_alloc_msg();
 | 
						|
 | 
						|
    if (msg == NULL) {
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    msg->type = MAC_MSG_TYPE_PM;
 | 
						|
    msg->id = MAC_MSG_ID_PWR_CHANGE;
 | 
						|
    msg->data1 = timer_id;
 | 
						|
    msg->data2 = arg;
 | 
						|
 | 
						|
    mac_queue_msg(msg, MAC_MSG_QUEUE_HP);
 | 
						|
out:
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void low_pwr_for_powroff_cfg_internal(timer_id_t timer_id, void * arg)
 | 
						|
{
 | 
						|
    (void)timer_id;
 | 
						|
    mac_pdev_t *pdev_ptr = (mac_pdev_t*)arg;
 | 
						|
    mac_vdev_t * vdev = pdev_ptr->vdev[PLC_DEFAULT_VDEV];
 | 
						|
    (void)vdev;
 | 
						|
 | 
						|
    if (g_phy_cpu_share_ctxt.tx_pwr_ctl_ena == 0 ||
 | 
						|
        pdev_ptr->mac_pm.mac_pm_flag) {
 | 
						|
        uint8_t hplc_power = 0;
 | 
						|
        int8_t rf_power = RF_TX_PWR_INVALID;
 | 
						|
        mac_set_tx_power_cap(vdev, &hplc_power, &rf_power, 1);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
uint32_t mac_pm_switch_by_fc_ok(uint8_t *mac_addr)
 | 
						|
{
 | 
						|
    IOT_ASSERT(mac_addr);
 | 
						|
    uint32_t ret = 0;
 | 
						|
    const uint8_t addr1[6]={0x11,0x00,0x00,0x00,0x00,0x01};
 | 
						|
    const uint8_t addr2[6]={0x11,0x00,0x00,0x00,0x00,0x02};
 | 
						|
    const uint8_t addr3[6]={0x11,0x00,0x00,0x00,0x00,0x03};
 | 
						|
    const uint8_t addr4[6]={0x11,0x00,0x00,0x00,0x00,0x04};
 | 
						|
    const uint8_t addr5[6]={0x11,0x00,0x00,0x00,0x00,0x05};
 | 
						|
    const uint8_t addr6[6]={0x11,0x00,0x00,0x00,0x00,0x06};
 | 
						|
    const uint8_t addr7[6]={0x11,0x00,0x00,0x00,0x00,0x07};
 | 
						|
    const uint8_t addr8[6]={0x11,0x00,0x00,0x00,0x00,0x08};
 | 
						|
    iot_printf("---%s:"
 | 
						|
            "0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
 | 
						|
            __FUNCTION__,
 | 
						|
            mac_addr[0],
 | 
						|
            mac_addr[1],
 | 
						|
            mac_addr[2],
 | 
						|
            mac_addr[3],
 | 
						|
            mac_addr[4],
 | 
						|
            mac_addr[5]
 | 
						|
            );
 | 
						|
    if (((iot_mac_addr_cmp(mac_addr, addr1) ||
 | 
						|
        iot_mac_addr_cmp(mac_addr, addr2) ||
 | 
						|
        iot_mac_addr_cmp(mac_addr, addr3) ||
 | 
						|
        iot_mac_addr_cmp(mac_addr, addr4) ||
 | 
						|
        iot_mac_addr_cmp(mac_addr, addr5) ||
 | 
						|
        iot_mac_addr_cmp(mac_addr, addr6) ||
 | 
						|
        iot_mac_addr_cmp(mac_addr, addr7) ||
 | 
						|
        iot_mac_addr_cmp(mac_addr, addr8)) &&
 | 
						|
        (USER_TYPE_SOUTHEN_POWER_GRID_HAINAN ==
 | 
						|
        iot_oem_get_user_type())) || RX_FC_ON_POWER_SAVE) {
 | 
						|
            iot_printf("enter sleep mode always\n");
 | 
						|
            ret = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 |