pinctrl: qcom: stub support for special GPIOs

Most platforms have a handful of "special" GPIOs, like the MMC
clock/data lanes, UFS reset, etc. These don't follow the usual naming
scheme of "gpioX" and also have unique capabilities and registers. We
can get away without supporting them all for now, but DT compatibility
is still an issue.

Add support for allowing these to be specified after the other pins, and
make all pinmux/pinconf calls for them nop.

Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Reviewed-by: Sumit Garg <sumit.garg@linaro.org>
Tested-by: Sumit Garg <sumit.garg@linaro.org> #qcs404
Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
diff --git a/drivers/pinctrl/qcom/pinctrl-apq8016.c b/drivers/pinctrl/qcom/pinctrl-apq8016.c
index 8149ffd..c860b74 100644
--- a/drivers/pinctrl/qcom/pinctrl-apq8016.c
+++ b/drivers/pinctrl/qcom/pinctrl-apq8016.c
@@ -55,7 +55,10 @@
 }
 
 static const struct msm_pinctrl_data apq8016_data = {
-	.pin_data = { .pin_count = 133, },
+	.pin_data = {
+		.pin_count = 133,
+		.special_pins_start = 122,
+	},
 	.functions_count = ARRAY_SIZE(msm_pinctrl_functions),
 	.get_function_name = apq8016_get_function_name,
 	.get_function_mux = apq8016_get_function_mux,
diff --git a/drivers/pinctrl/qcom/pinctrl-apq8096.c b/drivers/pinctrl/qcom/pinctrl-apq8096.c
index d64ab1f..75d1d09 100644
--- a/drivers/pinctrl/qcom/pinctrl-apq8096.c
+++ b/drivers/pinctrl/qcom/pinctrl-apq8096.c
@@ -50,7 +50,10 @@
 }
 
 static const struct msm_pinctrl_data apq8096_data = {
-	.pin_data = { .pin_count = 157, },
+	.pin_data = {
+		.pin_count = 157,
+		.special_pins_start = 150,
+	},
 	.functions_count = ARRAY_SIZE(msm_pinctrl_functions),
 	.get_function_name = apq8096_get_function_name,
 	.get_function_mux = apq8096_get_function_mux,
diff --git a/drivers/pinctrl/qcom/pinctrl-ipq4019.c b/drivers/pinctrl/qcom/pinctrl-ipq4019.c
index 2d99f99..74c04ab 100644
--- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c
@@ -46,7 +46,10 @@
 }
 
 static const struct msm_pinctrl_data ipq4019_data = {
-	.pin_data = { .pin_count = 100, },
+	.pin_data = {
+		.pin_count = 100,
+		.special_pins_start = 100, /* There are no special pins */
+	},
 	.functions_count = ARRAY_SIZE(msm_pinctrl_functions),
 	.get_function_name = ipq4019_get_function_name,
 	.get_function_mux = ipq4019_get_function_mux,
diff --git a/drivers/pinctrl/qcom/pinctrl-qcom.c b/drivers/pinctrl/qcom/pinctrl-qcom.c
index dc3d8c4..ee0624d 100644
--- a/drivers/pinctrl/qcom/pinctrl-qcom.c
+++ b/drivers/pinctrl/qcom/pinctrl-qcom.c
@@ -16,6 +16,7 @@
 #include <asm/gpio.h>
 #include <dm/pinctrl.h>
 #include <linux/bitops.h>
+#include <linux/bug.h>
 #include <mach/gpio.h>
 
 #include "pinctrl-qcom.h"
@@ -83,6 +84,10 @@
 {
 	struct msm_pinctrl_priv *priv = dev_get_priv(dev);
 
+	/* Always NOP for special pins, assume they're in the correct state */
+	if (qcom_is_special_pin(&priv->data->pin_data, pin_selector))
+		return 0;
+
 	clrsetbits_le32(priv->base + GPIO_CONFIG_REG(priv, pin_selector),
 			TLMM_FUNC_SEL_MASK | TLMM_GPIO_DISABLE,
 			priv->data->get_function_mux(func_selector) << 2);
@@ -94,6 +99,10 @@
 {
 	struct msm_pinctrl_priv *priv = dev_get_priv(dev);
 
+	/* Always NOP for special pins */
+	if (qcom_is_special_pin(&priv->data->pin_data, pin_selector))
+		return 0;
+
 	switch (param) {
 	case PIN_CONFIG_DRIVE_STRENGTH:
 		argument = (argument / 2) - 1;
@@ -136,6 +145,9 @@
 	const char *name;
 	int ret;
 
+	if (!data->pin_data.special_pins_start)
+		dev_warn(dev, "Special pins start index not defined!\n");
+
 	drv = lists_driver_lookup_name("pinctrl_qcom");
 	if (!drv)
 		return -ENOENT;
diff --git a/drivers/pinctrl/qcom/pinctrl-qcs404.c b/drivers/pinctrl/qcom/pinctrl-qcs404.c
index ac00afa..b54c8d8 100644
--- a/drivers/pinctrl/qcom/pinctrl-qcs404.c
+++ b/drivers/pinctrl/qcom/pinctrl-qcs404.c
@@ -61,8 +61,11 @@
 	return msm_pinctrl_functions[selector].val;
 }
 
-static struct msm_pinctrl_data qcs404_data = {
-	.pin_data = { .pin_count = 126, },
+static const struct msm_pinctrl_data qcs404_data = {
+	.pin_data = {
+		.pin_count = 126,
+		.special_pins_start = 120,
+	},
 	.functions_count = ARRAY_SIZE(msm_pinctrl_functions),
 	.get_function_name = qcs404_get_function_name,
 	.get_function_mux = qcs404_get_function_mux,
diff --git a/drivers/pinctrl/qcom/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c
index 9f0f408..76bd8c4 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdm845.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c
@@ -75,10 +75,11 @@
 	return msm_pinctrl_functions[selector].val;
 }
 
-static struct msm_pinctrl_data sdm845_data = {
+static const struct msm_pinctrl_data sdm845_data = {
 	.pin_data = {
 		.pin_offsets = sdm845_pin_offsets,
-		.pin_count = ARRAY_SIZE(sdm845_pin_offsets),
+		.pin_count = 154,
+		.special_pins_start = 150,
 	},
 	.functions_count = ARRAY_SIZE(msm_pinctrl_functions),
 	.get_function_name = sdm845_get_function_name,