summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2019-09-23 00:43:38 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2019-09-23 00:43:38 -0700
commitc7e9684caf25f542179461d58d4de127cd809d1c (patch)
treeb3a681131a2a9eb8b783df45035fb75e5e87f770
parent16ede3da1a2f9ce05c3980905b2de1484cbea170 (diff)
parent63058361746dfffebabded6c741665059985dcd0 (diff)
Merge "cnss2: support wakeup using gpio"
-rw-r--r--drivers/net/wireless/cnss2/main.c34
-rw-r--r--drivers/net/wireless/cnss2/main.h3
-rw-r--r--drivers/net/wireless/cnss2/power.c52
3 files changed, 88 insertions, 1 deletions
diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c
index 498650e08d2a..baa469ad2f6a 100644
--- a/drivers/net/wireless/cnss2/main.c
+++ b/drivers/net/wireless/cnss2/main.c
@@ -61,6 +61,40 @@ module_param(quirks, ulong, 0600);
MODULE_PARM_DESC(quirks, "Debug quirks for the driver");
#endif
+static unsigned int wow_wake_gpionum;
+#ifdef CONFIG_CNSS2_DEBUG
+module_param(wow_wake_gpionum, uint, 0600);
+MODULE_PARM_DESC(wow_wake_gpionum, "configure gpio number for wow wake");
+#endif
+
+static unsigned int wow_wake_enable;
+int cnss_enable_wow_wake(const char *val, const struct kernel_param *kp)
+{
+ int ret;
+ unsigned int prev_val;
+
+ prev_val = *(unsigned int *)kp->arg;
+ ret = param_set_uint(val, kp);
+ if (ret || prev_val == wow_wake_enable) {
+ cnss_pr_err("failed set new wow_enable ret = %d", ret);
+ return ret;
+ }
+ if (wow_wake_enable) {
+ if (!wow_wake_gpionum)
+ wow_wake_gpionum = HOST_WAKE_GPIO_IN;
+ cnss_set_wlan_chip_to_host_wakeup(wow_wake_gpionum);
+ }
+ return 0;
+}
+
+static const struct kernel_param_ops cnss_param_ops_uint = {
+ .set = &cnss_enable_wow_wake,
+ .get = &param_get_uint
+};
+
+module_param_cb(wow_wake_enable, &cnss_param_ops_uint,
+ &wow_wake_enable, 0600);
+
static struct cnss_fw_files FW_FILES_QCA6174_FW_3_0 = {
"qwlan30.bin", "bdwlan30.bin", "otp30.bin", "utf30.bin",
"utfbd30.bin", "epping30.bin", "evicted30.bin"
diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h
index 1b7c67b90795..524a1fa0dcf4 100644
--- a/drivers/net/wireless/cnss2/main.h
+++ b/drivers/net/wireless/cnss2/main.h
@@ -31,6 +31,7 @@
#define CNSS_EVENT_SYNC_UNINTERRUPTIBLE (CNSS_EVENT_SYNC | \
CNSS_EVENT_UNINTERRUPTIBLE)
#define QCN7605_CALDB_SIZE 614400
+#define HOST_WAKE_GPIO_IN 144
enum cnss_dev_bus_type {
CNSS_BUS_NONE = -1,
@@ -259,4 +260,6 @@ void cnss_set_pin_connect_status(struct cnss_plat_data *plat_priv);
u32 cnss_get_wake_msi(struct cnss_plat_data *plat_priv);
bool *cnss_get_qmi_bypass(void);
bool is_qcn7605_device(u16 device_id);
+void cnss_set_wlan_chip_to_host_wakeup(unsigned int wakeup_gpio_num);
+int cnss_enable_wow_wake(const char *val, const struct kernel_param *kp);
#endif /* _CNSS_MAIN_H */
diff --git a/drivers/net/wireless/cnss2/power.c b/drivers/net/wireless/cnss2/power.c
index 8a58a5357765..ed145d7049be 100644
--- a/drivers/net/wireless/cnss2/power.c
+++ b/drivers/net/wireless/cnss2/power.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -14,6 +14,7 @@
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/regulator/consumer.h>
+#include <linux/gpio.h>
#include "main.h"
#include "debug.h"
@@ -388,3 +389,52 @@ void cnss_set_pin_connect_status(struct cnss_plat_data *plat_priv)
plat_priv->pin_result.host_pin_result = pin_status;
}
+
+static irqreturn_t wlan_wakeup_interrupt(int irq, void *dev_id)
+{
+ return IRQ_HANDLED;
+}
+
+void cnss_set_wlan_chip_to_host_wakeup(unsigned int wakeup_gpio_num)
+{
+ int ret = 0;
+ int wakeup_irq_num;
+
+ ret = gpio_request(wakeup_gpio_num, "qcom_wlan_wakeup");
+ if (ret)
+ cnss_pr_err("wakeup gpio request failed\n");
+
+ ret = gpio_direction_input(wakeup_gpio_num);
+ if (ret) {
+ cnss_pr_err("wake gpio set dir output failed\n");
+ goto free_gpio;
+ }
+
+ wakeup_irq_num = gpio_to_irq(wakeup_gpio_num);
+ if (wakeup_irq_num < 0) {
+ cnss_pr_err("wake gpio_to_irq err %d\n", wakeup_irq_num);
+ goto free_gpio;
+ }
+ ret = request_irq(wakeup_irq_num, wlan_wakeup_interrupt,
+ IRQF_TRIGGER_FALLING, "qcom_wlan_wakeup_irq", NULL);
+ if (ret) {
+ cnss_pr_err("request_irq err %d\n", ret);
+ goto free_gpio;
+ }
+
+ ret = enable_irq_wake(wakeup_irq_num);
+ if (!ret) {
+ cnss_pr_err("enable irq wakeup success %d\n", ret);
+ } else {
+ cnss_pr_err("enable irq wakeup FAILURE %d\n", ret);
+ goto irq_free;
+ }
+ ret = gpio_get_value(wakeup_gpio_num);
+ cnss_pr_err("gpio get val ret = %d wakeup_gpio_num %d\n", ret,
+ wakeup_gpio_num);
+ return;
+irq_free:
+ free_irq(wakeup_irq_num, NULL);
+free_gpio:
+ gpio_free(wakeup_gpio_num);
+}