From 767c20875553eefdbb33738740232e422005bdba Mon Sep 17 00:00:00 2001
From: Hardik Kantilal Patel <hkpatel@codeaurora.org>
Date: Sun, 2 Mar 2014 09:16:37 -0800
Subject: [PATCH] wcnss: Add Pinctrl support for GPIO
Add Pinctrl support to configure 5 wire gpio interface
between Pronto and IRIS RF card.
Change-Id: I145cc91db6c66349034d70fa90dbd427026838f1
CRs-fixed: 567674
Signed-off-by: Hardik Kantilal Patel <hkpatel@codeaurora.org>
---
.../devicetree/bindings/wcnss/wcnss-wlan.txt | 6 +
arch/arm/boot/dts/qcom/msm8916-pinctrl.dtsi | 20 ++++
arch/arm/boot/dts/qcom/msm8916.dtsi | 4 +
drivers/net/wireless/wcnss/wcnss_wlan.c | 104 ++++++++++++++++--
4 files changed, 125 insertions(+), 9 deletions(-)
diff --git a/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt b/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
index 1a1ea6289bbf..615eae840e08 100644
--- a/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
+++ b/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
@@ -26,6 +26,8 @@ Required properties:
- qcom,has-48mhz-xo: boolean flag to determine the usage of 24MHz XO from RF
- qcom,has-pronto-hw: boolean flag to determine the revId of the WLAN subsystem
- qcom,wcnss-adc_tm: ADC handle for vbatt notification APIs.
+- pinctrl-<n> : Pinctrl states as described in bindings/pinctrl/pinctrl-bindings.txt
+- pinctrl-names : Names corresponding to the numbered pinctrl states
Optional properties:
- qcom,has-autodetect-xo: boolean flag to determine whether Iris XO auto detect
@@ -56,4 +58,8 @@ Example:
qcom,has-48mhz-xo;
qcom,has-pronto-hw;
qcom,wcnss-adc_tm = <&pm8226_adc_tm>;
+
+ pinctrl-names = "wcnss_default", "wcnss_sleep";
+ pinctrl-0 = <&wcnss_default>;
+ pinctrl-1 = <&wcnss_sleep>;
};
diff --git a/arch/arm/boot/dts/qcom/msm8916-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msm8916-pinctrl.dtsi
index 9f0aa72677d5..78c091e28358 100644
--- a/arch/arm/boot/dts/qcom/msm8916-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8916-pinctrl.dtsi
@@ -433,6 +433,7 @@
drive-strength = <3>; /* 3 MA */
};
};
+
pmx_mdss: pmx_mdss {
label = "mdss-pins";
mdss_dsi_active: active {
@@ -447,6 +448,25 @@
};
};
+ wcnss_pmux: wcnss_pmux {
+ /* Uses general purpose pins */
+ qcom,pins = <&gp 40>, <&gp 41>,
+ <&gp 42>, <&gp 43>,
+ <&gp 44>;
+ qcom,num-grp-pins = <5>;
+ qcom,pin-func = <1>;
+ label = "wcnss_pins";
+ /* Active configuration of bus pins */
+ wcnss_default: wcnss_default {
+ drive-strength = <6>; /* 6 MA */
+ bias-pull-up; /* PULL UP */
+ };
+ wcnss_sleep: wcnss_sleep {
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL Down */
+ };
+ };
+
/* CoreSight */
tpiu_seta_1 {
qcom,pins = <&gp 8>;
diff --git a/arch/arm/boot/dts/qcom/msm8916.dtsi b/arch/arm/boot/dts/qcom/msm8916.dtsi
index 8b0c7850514a..ec04d2d16210 100644
--- a/arch/arm/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8916.dtsi
@@ -1150,6 +1150,10 @@
qcom,iris-vddpa-supply = <&pm8916_l9>;
qcom,iris-vdddig-supply = <&pm8916_l5>;
+ pinctrl-names = "wcnss_default", "wcnss_sleep";
+ pinctrl-0 = <&wcnss_default>;
+ pinctrl-1 = <&wcnss_sleep>;
+
qcom,has-autodetect-xo;
qcom,has-pronto-hw;
};
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index af75b8af7f69..c7af923c653b 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -35,6 +35,7 @@
#include <linux/rwsem.h>
#include <linux/mfd/pm8xxx/misc.h>
#include <linux/qpnp/qpnp-adc.h>
+#include <linux/pinctrl/consumer.h>
#include <soc/qcom/subsystem_restart.h>
#include <soc/qcom/subsystem_notif.h>
@@ -52,6 +53,9 @@
#define VERSION "1.01"
#define WCNSS_PIL_DEVICE "wcnss"
+#define WCNSS_PINCTRL_STATE_DEFAULT "wcnss_default"
+#define WCNSS_PINCTRL_STATE_SLEEP "wcnss_sleep"
+
/* module params */
#define WCNSS_CONFIG_UNSPECIFIED (-1)
#define UINT32_MAX (0xFFFFFFFFU)
@@ -384,6 +388,10 @@ static struct {
u16 unsafe_ch_count;
u16 unsafe_ch_list[WCNSS_MAX_CH_NUM];
void *wcnss_notif_hdle;
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *gpio_state_active;
+ struct pinctrl_state *gpio_state_suspend;
+ int use_pinctrl;
} *penv = NULL;
static ssize_t wcnss_wlan_macaddr_store(struct device *dev,
@@ -922,14 +930,91 @@ static void wcnss_smd_notify_event(void *data, unsigned int event)
}
static int
-wcnss_pronto_gpios_config(struct device *dev, bool enable)
+wcnss_pinctrl_set_state(bool active)
+{
+ struct pinctrl_state *pin_state;
+ int ret;
+
+ pr_debug("%s: Set GPIO state : %d\n", __func__, active);
+
+ pin_state = active ? penv->gpio_state_active
+ : penv->gpio_state_suspend;
+
+ if (!IS_ERR_OR_NULL(pin_state)) {
+ ret = pinctrl_select_state(penv->pinctrl, pin_state);
+ if (ret < 0) {
+ pr_err("%s: can not set %s pins\n", __func__,
+ active ? WCNSS_PINCTRL_STATE_DEFAULT
+ : WCNSS_PINCTRL_STATE_SLEEP);
+ return ret;
+ }
+ } else {
+ pr_err("%s: invalid '%s' pinstate\n", __func__,
+ active ? WCNSS_PINCTRL_STATE_DEFAULT
+ : WCNSS_PINCTRL_STATE_SLEEP);
+ return PTR_ERR(pin_state);
+ }
+
+ return 0;
+}
+
+static int
+wcnss_pinctrl_init(struct platform_device *pdev)
+{
+ /* Get pinctrl if target uses pinctrl */
+ penv->pinctrl = devm_pinctrl_get(&pdev->dev);
+
+ if (IS_ERR_OR_NULL(penv->pinctrl)) {
+ pr_err("%s: failed to get pinctrl\n", __func__);
+ return PTR_ERR(penv->pinctrl);
+ }
+
+ penv->gpio_state_active
+ = pinctrl_lookup_state(penv->pinctrl,
+ WCNSS_PINCTRL_STATE_DEFAULT);
+
+ if (IS_ERR_OR_NULL(penv->gpio_state_active)) {
+ pr_err("%s: can not get default pinstate\n", __func__);
+ return PTR_ERR(penv->gpio_state_active);
+ }
+
+ penv->gpio_state_suspend
+ = pinctrl_lookup_state(penv->pinctrl,
+ WCNSS_PINCTRL_STATE_SLEEP);
+
+ if (IS_ERR_OR_NULL(penv->gpio_state_suspend)) {
+ pr_warn("%s: can not get sleep pinstate\n", __func__);
+ return PTR_ERR(penv->gpio_state_suspend);
+ }
+
+ return 0;
+}
+
+static int
+wcnss_pronto_gpios_config(struct platform_device *pdev, bool enable)
{
int rc = 0;
int i, j;
int WCNSS_WLAN_NUM_GPIOS = 5;
+ /* Use Pinctrl to configure 5 wire GPIOs */
+ rc = wcnss_pinctrl_init(pdev);
+ if (rc) {
+ pr_err("%s: failed to get pin resources\n", __func__);
+ penv->pinctrl = NULL;
+ goto gpio_probe;
+ } else {
+ rc = wcnss_pinctrl_set_state(true);
+ if (rc)
+ pr_err("%s: failed to set pin state\n",
+ __func__);
+ penv->use_pinctrl = true;
+ return rc;
+ }
+
+gpio_probe:
for (i = 0; i < WCNSS_WLAN_NUM_GPIOS; i++) {
- int gpio = of_get_gpio(dev->of_node, i);
+ int gpio = of_get_gpio(pdev->dev.of_node, i);
if (enable) {
rc = gpio_request(gpio, "wcnss_wlan");
if (rc) {
@@ -940,12 +1025,11 @@ wcnss_pronto_gpios_config(struct device *dev, bool enable)
} else
gpio_free(gpio);
}
-
return rc;
fail:
for (j = WCNSS_WLAN_NUM_GPIOS-1; j >= 0; j--) {
- int gpio = of_get_gpio(dev->of_node, i);
+ int gpio = of_get_gpio(pdev->dev.of_node, i);
gpio_free(gpio);
}
return rc;
@@ -2105,7 +2189,7 @@ wcnss_trigger_config(struct platform_device *pdev)
if (WCNSS_CONFIG_UNSPECIFIED == has_autodetect_xo && has_pronto_hw) {
has_autodetect_xo = of_property_read_bool(pdev->dev.of_node,
- "qcom,has-autodetect-xo");
+ "qcom,has-autodetect-xo");
}
penv->thermal_mitigation = 0;
@@ -2124,7 +2208,7 @@ wcnss_trigger_config(struct platform_device *pdev)
}
ret = wcnss_gpios_config(penv->gpios_5wire, true);
} else
- ret = wcnss_pronto_gpios_config(&pdev->dev, true);
+ ret = wcnss_pronto_gpios_config(pdev, true);
if (ret) {
dev_err(&pdev->dev, "WCNSS gpios config failed.\n");
@@ -2415,10 +2499,12 @@ fail_ioremap2:
fail_ioremap:
wake_lock_destroy(&penv->wcnss_wake_lock);
fail_res:
- if (has_pronto_hw)
- wcnss_pronto_gpios_config(&pdev->dev, false);
- else
+ if (!has_pronto_hw)
wcnss_gpios_config(penv->gpios_5wire, false);
+ else if (penv->use_pinctrl)
+ wcnss_pinctrl_set_state(false);
+ else
+ wcnss_pronto_gpios_config(pdev, false);
fail_gpio_res:
penv = NULL;
return ret;
--
GitLab