wcnss: Configuration of Iris 5-wire GPIOs by WCNSS driver
GPIOs tied to 5-wire interface to Iris must be controlled from within
WCNSS Platform Driver. This allows the platform driver to free the GPIO
resources and park them in a suspend mode (when appropriate) for power
savings
Change-Id: Ieaaf636f87e82e1b2c5b2ffa16b3a5d9e1c6fc33
Acked-by: Kumar Anand <kanand@qca.qualcomm.com>
Signed-off-by: Ankur Nandwani <ankurn@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index 97f1d3a..9610e33 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -463,7 +463,7 @@
static struct gpiomux_setting wcnss_5wire_suspend_cfg = {
.func = GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_NONE,
+ .pull = GPIOMUX_PULL_UP,
};
static struct gpiomux_setting wcnss_5wire_active_cfg = {
@@ -2099,6 +2099,12 @@
.name = "wcnss_mmio",
.flags = IORESOURCE_MEM,
},
+ {
+ .start = 84,
+ .end = 88,
+ .name = "wcnss_gpios_5wire",
+ .flags = IORESOURCE_IO,
+ },
};
static struct qcom_wcnss_opts qcom_wcnss_pdata = {
@@ -3762,29 +3768,6 @@
},
};
-static void msm8960_wcnss_init(void)
-{
- int i, ret, j;
-
- for (i = 0; i < ARRAY_SIZE(wcnss_5wire_interface); i++) {
- ret = gpio_request(wcnss_5wire_interface[i].gpio,
- "wcnss_5_wire");
- if (ret) {
- pr_err("wcnss_5_wire gpio %d failed: %d\n",
- wcnss_5wire_interface[i].gpio, ret);
- goto fail;
- }
- }
-
- pr_info("%s: Iris 5-wire gpios configured\n", __func__);
-
- return;
-
-fail:
- for (j = 0; j < i; j++)
- gpio_free(wcnss_5wire_interface[j].gpio);
-}
-
#ifdef CONFIG_KS8851
static int ethernet_init(void)
{
@@ -4206,7 +4189,6 @@
if (machine_is_msm8960_liquid())
mxt_init_hw_liquid();
register_i2c_devices();
- msm8960_wcnss_init();
msm_fb_add_devices();
slim_register_board_info(msm_slim_devices,
ARRAY_SIZE(msm_slim_devices));
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index d850a5e..e6945d5 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -20,6 +20,7 @@
#include <linux/platform_data/qcom_wcnss_device.h>
#include <linux/workqueue.h>
#include <linux/jiffies.h>
+#include <linux/gpio.h>
#include <mach/peripheral-loader.h>
#include "wcnss_riva.h"
@@ -40,6 +41,7 @@
struct resource *mmio_res;
struct resource *tx_irq_res;
struct resource *rx_irq_res;
+ struct resource *gpios_5wire;
const struct dev_pm_ops *pm_ops;
int smd_channel_ready;
struct wcnss_wlan_config wlan_config;
@@ -55,6 +57,31 @@
WCNSS_WLAN_SWITCH_OFF);
}
+static int
+wcnss_gpios_config(struct resource *gpios_5wire, bool enable)
+{
+ int i, j;
+ int rc = 0;
+
+ for (i = gpios_5wire->start; i <= gpios_5wire->end; i++) {
+ if (enable) {
+ rc = gpio_request(i, gpios_5wire->name);
+ if (rc) {
+ pr_err("WCNSS gpio_request %d err %d\n", i, rc);
+ goto fail;
+ }
+ } else
+ gpio_free(i);
+ }
+
+ return rc;
+
+fail:
+ for (j = i-1; j >= gpios_5wire->start; j--)
+ gpio_free(j);
+ return rc;
+}
+
static int __devinit
wcnss_wlan_ctrl_probe(struct platform_device *pdev)
{
@@ -189,6 +216,23 @@
has_48mhz_xo = pdata->has_48mhz_xo;
penv->wlan_config.use_48mhz_xo = has_48mhz_xo;
+ penv->gpios_5wire = platform_get_resource_byname(pdev, IORESOURCE_IO,
+ "wcnss_gpios_5wire");
+
+ /* allocate 5-wire GPIO resources */
+ if (!penv->gpios_5wire) {
+ dev_err(&pdev->dev, "insufficient IO resources\n");
+ ret = -ENOENT;
+ goto fail_gpio_res;
+ }
+
+ /* Configure 5 wire GPIOs */
+ ret = wcnss_gpios_config(penv->gpios_5wire, true);
+ if (ret) {
+ dev_err(&pdev->dev, "WCNSS gpios config failed.\n");
+ goto fail_gpio_res;
+ }
+
/* power up the WCNSS */
ret = wcnss_wlan_power(&pdev->dev, &penv->wlan_config,
WCNSS_WLAN_SWITCH_ON);
@@ -229,6 +273,8 @@
wcnss_wlan_power(&pdev->dev, &penv->wlan_config,
WCNSS_WLAN_SWITCH_OFF);
fail_power:
+ wcnss_gpios_config(penv->gpios_5wire, false);
+fail_gpio_res:
kfree(penv);
penv = NULL;
return ret;