Merge "icnss2: Send power save enter/exit via SMP2P"

This commit is contained in:
qctecmdr 2020-10-30 01:02:18 -07:00 • committed by Gerrit - the friendly Code Review server
commit 1e8e6c8d2b
2 changed files with 81 additions and 13 deletions

View file

@ -41,6 +41,8 @@
#include <soc/qcom/subsystem_restart.h>
#include <soc/qcom/socinfo.h>
#include <soc/qcom/ramdump.h>
#include <linux/soc/qcom/smem.h>
#include <linux/soc/qcom/smem_state.h>
#include "main.h"
#include "qmi.h"
#include "debug.h"
@ -2761,6 +2763,8 @@ EXPORT_SYMBOL(icnss_idle_restart);
int icnss_exit_power_save(struct device *dev)
{
struct icnss_priv *priv = dev_get_drvdata(dev);
unsigned int value = 0;
int ret;
icnss_pr_dbg("Calling Exit Power Save\n");
@ -2768,8 +2772,18 @@ int icnss_exit_power_save(struct device *dev)
!test_bit(ICNSS_MODE_ON, &priv->state))
return 0;
return wlfw_power_save_send_msg(priv,
(enum wlfw_power_save_mode_v01)ICNSS_POWER_SAVE_EXIT);
value |= priv->smp2p_info.seq++;
value <<= ICNSS_SMEM_SEQ_NO_POS;
value |= ICNSS_POWER_SAVE_EXIT;
ret = qcom_smem_state_update_bits(
priv->smp2p_info.smem_state,
ICNSS_SMEM_VALUE_MASK,
value);
if (ret)
icnss_pr_dbg("Error in SMP2P sent ret: %d\n", ret);
icnss_pr_dbg("SMP2P sent value: 0x%X\n", value);
return ret;
}
EXPORT_SYMBOL(icnss_exit_power_save);
@ -3154,6 +3168,20 @@ static void icnss_init_control_params(struct icnss_priv *priv)
}
}
static inline void icnss_get_smp2p_info(struct icnss_priv *priv)
{
priv->smp2p_info.smem_state =
qcom_smem_state_get(&priv->pdev->dev,
"wlan-smp2p-out",
&priv->smp2p_info.smem_bit);
if (IS_ERR(priv->smp2p_info.smem_state)) {
icnss_pr_dbg("Failed to get smem state %d",
PTR_ERR(priv->smp2p_info.smem_state));
}
}
static inline void icnss_runtime_pm_init(struct icnss_priv *priv)
{
pm_runtime_get_sync(&priv->pdev->dev);
@ -3275,6 +3303,7 @@ static int icnss_probe(struct platform_device *pdev)
icnss_runtime_pm_init(priv);
icnss_get_cpr_info(priv);
icnss_get_smp2p_info(priv);
set_bit(ICNSS_COLD_BOOT_CAL, &priv->state);
}
@ -3344,6 +3373,7 @@ static int icnss_remove(struct platform_device *pdev)
static int icnss_pm_suspend(struct device *dev)
{
struct icnss_priv *priv = dev_get_drvdata(dev);
unsigned int value = 0;
int ret = 0;
if (priv->magic != ICNSS_MAGIC) {
@ -3355,6 +3385,7 @@ static int icnss_pm_suspend(struct device *dev)
icnss_pr_vdbg("PM Suspend, state: 0x%lx\n", priv->state);
if (!priv->ops || !priv->ops->pm_suspend ||
IS_ERR(priv->smp2p_info.smem_state) ||
!test_bit(ICNSS_DRIVER_PROBED, &priv->state))
return 0;
@ -3362,11 +3393,23 @@ static int icnss_pm_suspend(struct device *dev)
if (ret == 0) {
if (priv->device_id == WCN6750_DEVICE_ID) {
ret = wlfw_power_save_send_msg(priv,
(enum wlfw_power_save_mode_v01)
ICNSS_POWER_SAVE_ENTER);
if (test_bit(ICNSS_PD_RESTART, &priv->state) ||
!test_bit(ICNSS_MODE_ON, &priv->state))
return 0;
value |= priv->smp2p_info.seq++;
value <<= ICNSS_SMEM_SEQ_NO_POS;
value |= ICNSS_POWER_SAVE_ENTER;
ret = qcom_smem_state_update_bits(
priv->smp2p_info.smem_state,
ICNSS_SMEM_VALUE_MASK,
value);
if (ret)
return priv->ops->pm_resume(dev);
icnss_pr_dbg("Error in SMP2P sent ret: %d\n",
ret);
icnss_pr_dbg("SMP2P sent value: 0x%X\n", value);
}
priv->stats.pm_suspend++;
set_bit(ICNSS_PM_SUSPEND, &priv->state);
@ -3390,6 +3433,7 @@ static int icnss_pm_resume(struct device *dev)
icnss_pr_vdbg("PM resume, state: 0x%lx\n", priv->state);
if (!priv->ops || !priv->ops->pm_resume ||
IS_ERR(priv->smp2p_info.smem_state) ||
!test_bit(ICNSS_DRIVER_PROBED, &priv->state))
goto out;
@ -3467,6 +3511,7 @@ out:
static int icnss_pm_runtime_suspend(struct device *dev)
{
struct icnss_priv *priv = dev_get_drvdata(dev);
unsigned int value = 0;
int ret = 0;
if (priv->magic != ICNSS_MAGIC) {
@ -3475,17 +3520,29 @@ static int icnss_pm_runtime_suspend(struct device *dev)
return -EINVAL;
}
if (!priv->ops || !priv->ops->runtime_suspend)
if (!priv->ops || !priv->ops->runtime_suspend ||
IS_ERR(priv->smp2p_info.smem_state))
goto out;
icnss_pr_vdbg("Runtime suspend\n");
ret = priv->ops->runtime_suspend(dev);
if (!ret) {
ret = wlfw_power_save_send_msg(priv,
(enum wlfw_power_save_mode_v01)
ICNSS_POWER_SAVE_ENTER);
if (test_bit(ICNSS_PD_RESTART, &priv->state) ||
!test_bit(ICNSS_MODE_ON, &priv->state))
return 0;
value |= priv->smp2p_info.seq++;
value <<= ICNSS_SMEM_SEQ_NO_POS;
value |= ICNSS_POWER_SAVE_ENTER;
ret = qcom_smem_state_update_bits(
priv->smp2p_info.smem_state,
ICNSS_SMEM_VALUE_MASK,
value);
if (ret)
return priv->ops->runtime_resume(dev);
icnss_pr_dbg("Error in SMP2P sent ret: %d\n", ret);
icnss_pr_dbg("SMP2P sent value: 0x%X\n", value);
}
out:
return ret;
@ -3502,7 +3559,8 @@ static int icnss_pm_runtime_resume(struct device *dev)
return -EINVAL;
}
if (!priv->ops || !priv->ops->runtime_resume)
if (!priv->ops || !priv->ops->runtime_resume ||
IS_ERR(priv->smp2p_info.smem_state))
goto out;
icnss_pr_vdbg("Runtime resume, state: 0x%lx\n", priv->state);

View file

@ -22,6 +22,9 @@
#define ADRASTEA_DEVICE_ID 0xabcd
#define QMI_WLFW_MAX_NUM_MEM_SEG 32
#define THERMAL_NAME_LENGTH 20
#define ICNSS_SMEM_VALUE_MASK 0xFFFFFFFF
#define ICNSS_SMEM_SEQ_NO_POS 16
extern uint64_t dynamic_feature_mask;
enum icnss_bdf_type {
@ -169,7 +172,7 @@ struct icnss_fw_mem {
};
enum icnss_power_save_mode {
ICNSS_POWER_SAVE_ENTER,
ICNSS_POWER_SAVE_ENTER = 1,
ICNSS_POWER_SAVE_EXIT,
};
struct icnss_stats {
@ -310,6 +313,12 @@ struct icnss_thermal_cdev {
struct thermal_cooling_device *tcdev;
};
struct smp2p_out_info {
unsigned short seq;
unsigned int smem_bit;
struct qcom_smem_state *smem_state;
};
struct icnss_priv {
uint32_t magic;
struct platform_device *pdev;
@ -386,6 +395,7 @@ struct icnss_priv {
struct mutex dev_lock;
uint32_t fw_error_fatal_irq;
uint32_t fw_early_crash_irq;
struct smp2p_out_info smp2p_info;
struct completion unblock_shutdown;
struct adc_tm_param vph_monitor_params;
struct adc_tm_chip *adc_tm_dev;