Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 66a8db13 authored by Siddharth Bhal's avatar Siddharth Bhal
Browse files

wcnss: add pm_qos support to prevent power collapse for BIMC



Add pm_qos support to prevent power collapse of BIMC during
SSR and coldboot. Wakelock is also taken to prevent power
collapse of BIMC

CRs-Fixed: 727070
Change-Id: Ida638e85995735b629ad455dd48df996b37c2305
Signed-off-by: default avatarSiddharth Bhal <sbhal@codeaurora.org>
parent a361376d
Loading
Loading
Loading
Loading
+74 −5
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include <linux/mfd/pm8xxx/misc.h>
#include <linux/qpnp/qpnp-adc.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pm_qos.h>

#include <soc/qcom/subsystem_restart.h>
#include <soc/qcom/subsystem_notif.h>
@@ -51,6 +52,10 @@
#define WCNSS_PINCTRL_STATE_SLEEP "wcnss_sleep"
#define WCNSS_PINCTRL_GPIO_STATE_DEFAULT "wcnss_gpio_default"

#define WCNSS_DISABLE_PC_LATENCY	100
#define WCNSS_ENABLE_PC_LATENCY	PM_QOS_DEFAULT_VALUE
#define WCNSS_PM_QOS_TIMEOUT	15000

/* module params */
#define WCNSS_CONFIG_UNSPECIFIED (-1)
#define UINT32_MAX (0xFFFFFFFFU)
@@ -409,6 +414,9 @@ static struct {
	int gpios[WCNSS_WLAN_MAX_GPIO];
	int use_pinctrl;
	u8 is_shutdown;
	struct pm_qos_request wcnss_pm_qos_request;
	int pc_disabled;
	struct delayed_work wcnss_pm_qos_del_req;
} *penv = NULL;

static ssize_t wcnss_wlan_macaddr_store(struct device *dev,
@@ -1115,6 +1123,46 @@ static void wcnss_remove_sysfs(struct device *dev)
		device_remove_file(dev, &dev_attr_wcnss_mac_addr);
	}
}

static void wcnss_pm_qos_add_request(void)
{
	pr_info("%s: add request", __func__);
	pm_qos_add_request(&penv->wcnss_pm_qos_request, PM_QOS_CPU_DMA_LATENCY,
			PM_QOS_DEFAULT_VALUE);
}

static void wcnss_pm_qos_remove_request(void)
{
	pr_info("%s: remove request", __func__);
	pm_qos_remove_request(&penv->wcnss_pm_qos_request);
}

void wcnss_pm_qos_update_request(int val)
{
	pr_info("%s: update request %d", __func__, val);
	pm_qos_update_request(&penv->wcnss_pm_qos_request, val);
}

void wcnss_disable_pc_remove_req(void)
{
	if (penv->pc_disabled) {
		wcnss_pm_qos_update_request(WCNSS_ENABLE_PC_LATENCY);
		wcnss_pm_qos_remove_request();
		wcnss_allow_suspend();
		penv->pc_disabled = 0;
	}
}

void wcnss_disable_pc_add_req(void)
{
	if (!penv->pc_disabled) {
		wcnss_pm_qos_add_request();
		wcnss_prevent_suspend();
		wcnss_pm_qos_update_request(WCNSS_DISABLE_PC_LATENCY);
		penv->pc_disabled = 1;
	}
}

static void wcnss_smd_notify_event(void *data, unsigned int event)
{
	int len = 0;
@@ -1138,6 +1186,8 @@ static void wcnss_smd_notify_event(void *data, unsigned int event)
				WCNSS_CTRL_CHANNEL);
		schedule_work(&penv->wcnssctrl_version_work);
		schedule_work(&penv->wcnss_pm_config_work);
		cancel_delayed_work(&penv->wcnss_pm_qos_del_req);
		schedule_delayed_work(&penv->wcnss_pm_qos_del_req, 0);

		break;

@@ -2122,6 +2172,11 @@ static void wcnss_send_pm_config(struct work_struct *worker)
	return;
}

static void wcnss_pm_qos_enable_pc(struct work_struct *worker)
{
	wcnss_disable_pc_remove_req();
	return;
}

static DECLARE_RWSEM(wcnss_pm_sem);

@@ -2552,8 +2607,11 @@ wcnss_trigger_config(struct platform_device *pdev)
	INIT_WORK(&penv->wcnssctrl_version_work, wcnss_send_version_req);
	INIT_WORK(&penv->wcnss_pm_config_work, wcnss_send_pm_config);
	INIT_WORK(&penv->wcnssctrl_nvbin_dnld_work, wcnss_nvbin_dnld_main);
	INIT_DELAYED_WORK(&penv->wcnss_pm_qos_del_req, wcnss_pm_qos_enable_pc);

	wake_lock_init(&penv->wcnss_wake_lock, WAKE_LOCK_SUSPEND, "wcnss");
	/* Add pm_qos request to disable power collapse for DDR */
	wcnss_disable_pc_add_req();

	if (wcnss_hardware_type() == WCNSS_PRONTO_HW) {
		res = platform_get_resource_byname(pdev,
@@ -2803,6 +2861,7 @@ wcnss_trigger_config(struct platform_device *pdev)
		if (IS_ERR(penv->pil)) {
			dev_err(&pdev->dev, "Peripheral Loader failed on WCNSS.\n");
			ret = PTR_ERR(penv->pil);
			wcnss_disable_pc_add_req();
			wcnss_pronto_log_debug_regs();
		}
	} while (pil_retry++ < WCNSS_MAX_PIL_RETRY && IS_ERR(penv->pil));
@@ -2815,6 +2874,8 @@ wcnss_trigger_config(struct platform_device *pdev)
		penv->pil = NULL;
		goto fail_ioremap2;
	}
	/* Remove pm_qos request */
	wcnss_disable_pc_remove_req();

	return 0;

@@ -2831,6 +2892,7 @@ fail_res:
	else
		wcnss_pronto_gpios_config(pdev, false);
fail_gpio_res:
	wcnss_disable_pc_remove_req();
	penv = NULL;
	return ret;
}
@@ -2962,7 +3024,7 @@ static int wcnss_notif_cb(struct notifier_block *this, unsigned long code,
	struct notif_data *data = (struct notif_data *)ss_handle;
	int ret, xo_mode;

	pr_debug("%s: wcnss notification event: %lu\n", __func__, code);
	pr_info("%s: wcnss notification event: %lu\n", __func__, code);

	if (code == SUBSYS_PROXY_VOTE) {
		if (pdev && pwlanconfig) {
@@ -2983,16 +3045,23 @@ static int wcnss_notif_cb(struct notifier_block *this, unsigned long code,
					WCNSS_WLAN_SWITCH_OFF, NULL);
		}
	} else if ((code == SUBSYS_BEFORE_SHUTDOWN && data && data->crashed) ||
						code == SUBSYS_SOC_RESET)
			code == SUBSYS_SOC_RESET) {
		wcnss_disable_pc_add_req();
		schedule_delayed_work(&penv->wcnss_pm_qos_del_req,
				msecs_to_jiffies(WCNSS_PM_QOS_TIMEOUT));
		wcnss_log_debug_regs_on_bite();
	else if (code == SUBSYS_POWERUP_FAILURE) {
	} else if (code == SUBSYS_POWERUP_FAILURE) {
		if (pdev && pwlanconfig)
			wcnss_wlan_power(&pdev->dev, pwlanconfig,
					WCNSS_WLAN_SWITCH_OFF, NULL);
		wcnss_pronto_log_debug_regs();
	} else if (SUBSYS_BEFORE_SHUTDOWN == code)
		wcnss_disable_pc_remove_req();
	} else if (SUBSYS_BEFORE_SHUTDOWN == code) {
		wcnss_disable_pc_add_req();
		schedule_delayed_work(&penv->wcnss_pm_qos_del_req,
				msecs_to_jiffies(WCNSS_PM_QOS_TIMEOUT));
		penv->is_shutdown = 1;
	else if (SUBSYS_AFTER_POWERUP == code)
	} else if (SUBSYS_AFTER_POWERUP == code)
		penv->is_shutdown = 0;

	return NOTIFY_DONE;