gpiolib: provide provision to register pin ranges

pinctrl subsystem needs gpio chip base to prepare set of gpio
pin ranges, which a given pinctrl driver can handle. This is
important to handle pinctrl gpio request calls in order to
program a given pin properly for gpio operation.

As gpio base is allocated dynamically during gpiochip
registration, presently there exists no clean way to pass this
information to the pinctrl subsystem.

After few discussions from [1], it was concluded that may be
gpio controller reporting the pin range it supports, is a
better way than pinctrl subsystem directly registering it.

[1] http://comments.gmane.org/gmane.linux.ports.arm.kernel/184816

Cc: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Shiraz Hashim <shiraz.hashim@st.com>
[Edited documentation a bit]
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index a9432fc..92e5c43 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -5,6 +5,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/of.h>
+#include <linux/pinctrl/pinctrl.h>
 
 #ifdef CONFIG_GPIOLIB
 
@@ -47,6 +48,21 @@
 struct module;
 struct device_node;
 
+#ifdef CONFIG_PINCTRL
+/**
+ * struct gpio_pin_range - pin range controlled by a gpio chip
+ * @head: list for maintaining set of pin ranges, used internally
+ * @pctldev: pinctrl device which handles corresponding pins
+ * @range: actual range of pins controlled by a gpio controller
+ */
+
+struct gpio_pin_range {
+	struct list_head node;
+	struct pinctrl_dev *pctldev;
+	struct pinctrl_gpio_range range;
+};
+#endif
+
 /**
  * struct gpio_chip - abstract a GPIO controller
  * @label: for diagnostics
@@ -134,6 +150,15 @@
 	int (*of_xlate)(struct gpio_chip *gc,
 		        const struct of_phandle_args *gpiospec, u32 *flags);
 #endif
+#ifdef CONFIG_PINCTRL
+	/*
+	 * If CONFIG_PINCTRL is enabled, then gpio controllers can optionally
+	 * describe the actual pin range which they serve in an SoC. This
+	 * information would be used by pinctrl subsystem to configure
+	 * corresponding pins for gpio usage.
+	 */
+	struct list_head pin_ranges;
+#endif
 };
 
 extern const char *gpiochip_is_requested(struct gpio_chip *chip,
diff --git a/include/linux/gpio.h b/include/linux/gpio.h
index 2e31e8b..a284459 100644
--- a/include/linux/gpio.h
+++ b/include/linux/gpio.h
@@ -231,6 +231,9 @@
 	return -EINVAL;
 }
 
+void gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+		unsigned int pin_base, unsigned int npins);
+void gpiochip_remove_pin_ranges(struct gpio_chip *chip);
 #endif
 
 #endif /* __LINUX_GPIO_H */
diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
index eda0467..434e5a9 100644
--- a/include/linux/pinctrl/pinctrl.h
+++ b/include/linux/pinctrl/pinctrl.h
@@ -136,6 +136,23 @@
 				unsigned nranges);
 extern void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
 				struct pinctrl_gpio_range *range);
+
+extern struct pinctrl_dev *find_pinctrl_and_add_gpio_range(const char *devname,
+		struct pinctrl_gpio_range *range);
+
+#ifdef CONFIG_OF
+extern struct pinctrl_dev *of_pinctrl_add_gpio_range(struct device_node *np,
+		struct pinctrl_gpio_range *range);
+#else
+static inline
+struct pinctrl_dev *of_pinctrl_add_gpio_range(struct device_node *np,
+		struct pinctrl_gpio_range *range)
+{
+	return NULL;
+}
+
+#endif /* CONFIG_OF */
+
 extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev);
 extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev);
 #else