aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRojhalat Ibrahim <imr@rtschenk.de>2015-02-11 11:27:58 -0500
committerLinus Walleij <linus.walleij@linaro.org>2015-03-05 03:52:28 -0500
commit668585273246f67b0cdafa30dd2da2047a2e1290 (patch)
treec6e3186d6aab7d08e0f50b5030be4bef4a8b17df
parent7f2e553a7173b485db41a52060f91fb8e5ab1c69 (diff)
gpiolib: add gpiod_get_array and gpiod_put_array functions
Introduce new functions for conveniently obtaining and disposing of an entire array of GPIOs with one function call. ACPI parts tested by Mika Westerberg, DT parts tested by Rojhalat Ibrahim. Change log: v5: move the ACPI functions to gpiolib-acpi.c v4: - use shorter names for members of struct gpio_descs - rename lut_gpio_count to platform_gpio_count for clarity - add check for successful memory allocation - use ERR_CAST() v3: - rebase on current linux-gpio devel branch - fix ACPI GPIO counting - allow for zero-sized arrays - make the flags argument mandatory for the new functions - clarify documentation v2: change interface Suggested-by: Alexandre Courbot <acourbot@nvidia.com> Signed-off-by: Rojhalat Ibrahim <imr@rtschenk.de> Reviewed-by: Alexandre Courbot <acourbot@nvidia.com> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com> Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com> Tested-by: Rojhalat Ibrahim <imr@rtschenk.de> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--Documentation/gpio/consumer.txt33
-rw-r--r--drivers/gpio/gpiolib-acpi.c84
-rw-r--r--drivers/gpio/gpiolib.c145
-rw-r--r--drivers/gpio/gpiolib.h7
-rw-r--r--include/linux/gpio/consumer.h46
5 files changed, 312 insertions, 3 deletions
diff --git a/Documentation/gpio/consumer.txt b/Documentation/gpio/consumer.txt
index d85fbae451ea..2924f2ffcd91 100644
--- a/Documentation/gpio/consumer.txt
+++ b/Documentation/gpio/consumer.txt
@@ -58,7 +58,6 @@ pattern where a GPIO is optional, the gpiod_get_optional() and
58gpiod_get_index_optional() functions can be used. These functions return NULL 58gpiod_get_index_optional() functions can be used. These functions return NULL
59instead of -ENOENT if no GPIO has been assigned to the requested function: 59instead of -ENOENT if no GPIO has been assigned to the requested function:
60 60
61
62 struct gpio_desc *gpiod_get_optional(struct device *dev, 61 struct gpio_desc *gpiod_get_optional(struct device *dev,
63 const char *con_id, 62 const char *con_id,
64 enum gpiod_flags flags) 63 enum gpiod_flags flags)
@@ -68,6 +67,27 @@ instead of -ENOENT if no GPIO has been assigned to the requested function:
68 unsigned int index, 67 unsigned int index,
69 enum gpiod_flags flags) 68 enum gpiod_flags flags)
70 69
70For a function using multiple GPIOs all of those can be obtained with one call:
71
72 struct gpio_descs *gpiod_get_array(struct device *dev,
73 const char *con_id,
74 enum gpiod_flags flags)
75
76This function returns a struct gpio_descs which contains an array of
77descriptors:
78
79 struct gpio_descs {
80 unsigned int ndescs;
81 struct gpio_desc *desc[];
82 }
83
84The following function returns NULL instead of -ENOENT if no GPIOs have been
85assigned to the requested function:
86
87 struct gpio_descs *gpiod_get_array_optional(struct device *dev,
88 const char *con_id,
89 enum gpiod_flags flags)
90
71Device-managed variants of these functions are also defined: 91Device-managed variants of these functions are also defined:
72 92
73 struct gpio_desc *devm_gpiod_get(struct device *dev, const char *con_id, 93 struct gpio_desc *devm_gpiod_get(struct device *dev, const char *con_id,
@@ -91,8 +111,15 @@ A GPIO descriptor can be disposed of using the gpiod_put() function:
91 111
92 void gpiod_put(struct gpio_desc *desc) 112 void gpiod_put(struct gpio_desc *desc)
93 113
94It is strictly forbidden to use a descriptor after calling this function. The 114For an array of GPIOs this function can be used:
95device-managed variant is, unsurprisingly: 115
116 void gpiod_put_array(struct gpio_descs *descs)
117
118It is strictly forbidden to use a descriptor after calling these functions.
119It is also not allowed to individually release descriptors (using gpiod_put())
120from an array acquired with gpiod_get_array().
121
122The device-managed variant is, unsurprisingly:
96 123
97 void devm_gpiod_put(struct device *dev, struct gpio_desc *desc) 124 void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
98 125
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index c0929d938ced..c4919966453d 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -712,3 +712,87 @@ void acpi_gpiochip_remove(struct gpio_chip *chip)
712 acpi_detach_data(handle, acpi_gpio_chip_dh); 712 acpi_detach_data(handle, acpi_gpio_chip_dh);
713 kfree(acpi_gpio); 713 kfree(acpi_gpio);
714} 714}
715
716static unsigned int acpi_gpio_package_count(const union acpi_object *obj)
717{
718 const union acpi_object *element = obj->package.elements;
719 const union acpi_object *end = element + obj->package.count;
720 unsigned int count = 0;
721
722 while (element < end) {
723 if (element->type == ACPI_TYPE_LOCAL_REFERENCE)
724 count++;
725
726 element++;
727 }
728 return count;
729}
730
731static int acpi_find_gpio_count(struct acpi_resource *ares, void *data)
732{
733 unsigned int *count = data;
734
735 if (ares->type == ACPI_RESOURCE_TYPE_GPIO)
736 *count += ares->data.gpio.pin_table_length;
737
738 return 1;
739}
740
741/**
742 * acpi_gpio_count - return the number of GPIOs associated with a
743 * device / function or -ENOENT if no GPIO has been
744 * assigned to the requested function.
745 * @dev: GPIO consumer, can be NULL for system-global GPIOs
746 * @con_id: function within the GPIO consumer
747 */
748int acpi_gpio_count(struct device *dev, const char *con_id)
749{
750 struct acpi_device *adev = ACPI_COMPANION(dev);
751 const union acpi_object *obj;
752 const struct acpi_gpio_mapping *gm;
753 int count = -ENOENT;
754 int ret;
755 char propname[32];
756 unsigned int i;
757
758 /* Try first from _DSD */
759 for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
760 if (con_id && strcmp(con_id, "gpios"))
761 snprintf(propname, sizeof(propname), "%s-%s",
762 con_id, gpio_suffixes[i]);
763 else
764 snprintf(propname, sizeof(propname), "%s",
765 gpio_suffixes[i]);
766
767 ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_ANY,
768 &obj);
769 if (ret == 0) {
770 if (obj->type == ACPI_TYPE_LOCAL_REFERENCE)
771 count = 1;
772 else if (obj->type == ACPI_TYPE_PACKAGE)
773 count = acpi_gpio_package_count(obj);
774 } else if (adev->driver_gpios) {
775 for (gm = adev->driver_gpios; gm->name; gm++)
776 if (strcmp(propname, gm->name) == 0) {
777 count = gm->size;
778 break;
779 }
780 }
781 if (count >= 0)
782 break;
783 }
784
785 /* Then from plain _CRS GPIOs */
786 if (count < 0) {
787 struct list_head resource_list;
788 unsigned int crs_count = 0;
789
790 INIT_LIST_HEAD(&resource_list);
791 acpi_dev_get_resources(adev, &resource_list,
792 acpi_find_gpio_count, &crs_count);
793 acpi_dev_free_resource_list(&resource_list);
794 if (crs_count > 0)
795 count = crs_count;
796 }
797 return count;
798}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 2f8296c021e5..3d5b85a7dcdf 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1806,6 +1806,70 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
1806 return desc; 1806 return desc;
1807} 1807}
1808 1808
1809static int dt_gpio_count(struct device *dev, const char *con_id)
1810{
1811 int ret;
1812 char propname[32];
1813 unsigned int i;
1814
1815 for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
1816 if (con_id)
1817 snprintf(propname, sizeof(propname), "%s-%s",
1818 con_id, gpio_suffixes[i]);
1819 else
1820 snprintf(propname, sizeof(propname), "%s",
1821 gpio_suffixes[i]);
1822
1823 ret = of_gpio_named_count(dev->of_node, propname);
1824 if (ret >= 0)
1825 break;
1826 }
1827 return ret;
1828}
1829
1830static int platform_gpio_count(struct device *dev, const char *con_id)
1831{
1832 struct gpiod_lookup_table *table;
1833 struct gpiod_lookup *p;
1834 unsigned int count = 0;
1835
1836 table = gpiod_find_lookup_table(dev);
1837 if (!table)
1838 return -ENOENT;
1839
1840 for (p = &table->table[0]; p->chip_label; p++) {
1841 if ((con_id && p->con_id && !strcmp(con_id, p->con_id)) ||
1842 (!con_id && !p->con_id))
1843 count++;
1844 }
1845 if (!count)
1846 return -ENOENT;
1847
1848 return count;
1849}
1850
1851/**
1852 * gpiod_count - return the number of GPIOs associated with a device / function
1853 * or -ENOENT if no GPIO has been assigned to the requested function
1854 * @dev: GPIO consumer, can be NULL for system-global GPIOs
1855 * @con_id: function within the GPIO consumer
1856 */
1857int gpiod_count(struct device *dev, const char *con_id)
1858{
1859 int count = -ENOENT;
1860
1861 if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node)
1862 count = dt_gpio_count(dev, con_id);
1863 else if (IS_ENABLED(CONFIG_ACPI) && dev && ACPI_HANDLE(dev))
1864 count = acpi_gpio_count(dev, con_id);
1865
1866 if (count < 0)
1867 count = platform_gpio_count(dev, con_id);
1868
1869 return count;
1870}
1871EXPORT_SYMBOL_GPL(gpiod_count);
1872
1809/** 1873/**
1810 * gpiod_get - obtain a GPIO for a given GPIO function 1874 * gpiod_get - obtain a GPIO for a given GPIO function
1811 * @dev: GPIO consumer, can be NULL for system-global GPIOs 1875 * @dev: GPIO consumer, can be NULL for system-global GPIOs
@@ -2090,6 +2154,72 @@ static void gpiochip_free_hogs(struct gpio_chip *chip)
2090} 2154}
2091 2155
2092/** 2156/**
2157 * gpiod_get_array - obtain multiple GPIOs from a multi-index GPIO function
2158 * @dev: GPIO consumer, can be NULL for system-global GPIOs
2159 * @con_id: function within the GPIO consumer
2160 * @flags: optional GPIO initialization flags
2161 *
2162 * This function acquires all the GPIOs defined under a given function.
2163 *
2164 * Return a struct gpio_descs containing an array of descriptors, -ENOENT if
2165 * no GPIO has been assigned to the requested function, or another IS_ERR()
2166 * code if an error occurred while trying to acquire the GPIOs.
2167 */
2168struct gpio_descs *__must_check gpiod_get_array(struct device *dev,
2169 const char *con_id,
2170 enum gpiod_flags flags)
2171{
2172 struct gpio_desc *desc;
2173 struct gpio_descs *descs;
2174 int count;
2175
2176 count = gpiod_count(dev, con_id);
2177 if (count < 0)
2178 return ERR_PTR(count);
2179
2180 descs = kzalloc(sizeof(*descs) + sizeof(descs->desc[0]) * count,
2181 GFP_KERNEL);
2182 if (!descs)
2183 return ERR_PTR(-ENOMEM);
2184
2185 for (descs->ndescs = 0; descs->ndescs < count; ) {
2186 desc = gpiod_get_index(dev, con_id, descs->ndescs, flags);
2187 if (IS_ERR(desc)) {
2188 gpiod_put_array(descs);
2189 return ERR_CAST(desc);
2190 }
2191 descs->desc[descs->ndescs] = desc;
2192 descs->ndescs++;
2193 }
2194 return descs;
2195}
2196EXPORT_SYMBOL_GPL(gpiod_get_array);
2197
2198/**
2199 * gpiod_get_array_optional - obtain multiple GPIOs from a multi-index GPIO
2200 * function
2201 * @dev: GPIO consumer, can be NULL for system-global GPIOs
2202 * @con_id: function within the GPIO consumer
2203 * @flags: optional GPIO initialization flags
2204 *
2205 * This is equivalent to gpiod_get_array(), except that when no GPIO was
2206 * assigned to the requested function it will return NULL.
2207 */
2208struct gpio_descs *__must_check gpiod_get_array_optional(struct device *dev,
2209 const char *con_id,
2210 enum gpiod_flags flags)
2211{
2212 struct gpio_descs *descs;
2213
2214 descs = gpiod_get_array(dev, con_id, flags);
2215 if (IS_ERR(descs) && (PTR_ERR(descs) == -ENOENT))
2216 return NULL;
2217
2218 return descs;
2219}
2220EXPORT_SYMBOL_GPL(gpiod_get_array_optional);
2221
2222/**
2093 * gpiod_put - dispose of a GPIO descriptor 2223 * gpiod_put - dispose of a GPIO descriptor
2094 * @desc: GPIO descriptor to dispose of 2224 * @desc: GPIO descriptor to dispose of
2095 * 2225 *
@@ -2101,6 +2231,21 @@ void gpiod_put(struct gpio_desc *desc)
2101} 2231}
2102EXPORT_SYMBOL_GPL(gpiod_put); 2232EXPORT_SYMBOL_GPL(gpiod_put);
2103 2233
2234/**
2235 * gpiod_put_array - dispose of multiple GPIO descriptors
2236 * @descs: struct gpio_descs containing an array of descriptors
2237 */
2238void gpiod_put_array(struct gpio_descs *descs)
2239{
2240 unsigned int i;
2241
2242 for (i = 0; i < descs->ndescs; i++)
2243 gpiod_put(descs->desc[i]);
2244
2245 kfree(descs);
2246}
2247EXPORT_SYMBOL_GPL(gpiod_put_array);
2248
2104#ifdef CONFIG_DEBUG_FS 2249#ifdef CONFIG_DEBUG_FS
2105 2250
2106static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) 2251static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index 205dd12659c0..54bc5ec91398 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -40,6 +40,8 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
40struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, 40struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
41 const char *propname, int index, 41 const char *propname, int index,
42 struct acpi_gpio_info *info); 42 struct acpi_gpio_info *info);
43
44int acpi_gpio_count(struct device *dev, const char *con_id);
43#else 45#else
44static inline void acpi_gpiochip_add(struct gpio_chip *chip) { } 46static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
45static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { } 47static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { }
@@ -56,6 +58,11 @@ acpi_get_gpiod_by_index(struct acpi_device *adev, const char *propname,
56{ 58{
57 return ERR_PTR(-ENOSYS); 59 return ERR_PTR(-ENOSYS);
58} 60}
61
62static inline int acpi_gpio_count(struct device *dev, const char *con_id)
63{
64 return -ENODEV;
65}
59#endif 66#endif
60 67
61struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, 68struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index ed20759229eb..33eb52fd0932 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -16,6 +16,15 @@ struct device;
16 */ 16 */
17struct gpio_desc; 17struct gpio_desc;
18 18
19/**
20 * Struct containing an array of descriptors that can be obtained using
21 * gpiod_get_array().
22 */
23struct gpio_descs {
24 unsigned int ndescs;
25 struct gpio_desc *desc[];
26};
27
19#define GPIOD_FLAGS_BIT_DIR_SET BIT(0) 28#define GPIOD_FLAGS_BIT_DIR_SET BIT(0)
20#define GPIOD_FLAGS_BIT_DIR_OUT BIT(1) 29#define GPIOD_FLAGS_BIT_DIR_OUT BIT(1)
21#define GPIOD_FLAGS_BIT_DIR_VAL BIT(2) 30#define GPIOD_FLAGS_BIT_DIR_VAL BIT(2)
@@ -34,6 +43,9 @@ enum gpiod_flags {
34 43
35#ifdef CONFIG_GPIOLIB 44#ifdef CONFIG_GPIOLIB
36 45
46/* Return the number of GPIOs associated with a device / function */
47int gpiod_count(struct device *dev, const char *con_id);
48
37/* Acquire and dispose GPIOs */ 49/* Acquire and dispose GPIOs */
38struct gpio_desc *__must_check __gpiod_get(struct device *dev, 50struct gpio_desc *__must_check __gpiod_get(struct device *dev,
39 const char *con_id, 51 const char *con_id,
@@ -49,7 +61,14 @@ struct gpio_desc *__must_check __gpiod_get_index_optional(struct device *dev,
49 const char *con_id, 61 const char *con_id,
50 unsigned int index, 62 unsigned int index,
51 enum gpiod_flags flags); 63 enum gpiod_flags flags);
64struct gpio_descs *__must_check gpiod_get_array(struct device *dev,
65 const char *con_id,
66 enum gpiod_flags flags);
67struct gpio_descs *__must_check gpiod_get_array_optional(struct device *dev,
68 const char *con_id,
69 enum gpiod_flags flags);
52void gpiod_put(struct gpio_desc *desc); 70void gpiod_put(struct gpio_desc *desc);
71void gpiod_put_array(struct gpio_descs *descs);
53 72
54struct gpio_desc *__must_check __devm_gpiod_get(struct device *dev, 73struct gpio_desc *__must_check __devm_gpiod_get(struct device *dev,
55 const char *con_id, 74 const char *con_id,
@@ -114,6 +133,11 @@ struct gpio_desc *devm_get_gpiod_from_child(struct device *dev,
114 struct fwnode_handle *child); 133 struct fwnode_handle *child);
115#else /* CONFIG_GPIOLIB */ 134#else /* CONFIG_GPIOLIB */
116 135
136static inline int gpiod_count(struct device *dev, const char *con_id)
137{
138 return 0;
139}
140
117static inline struct gpio_desc *__must_check __gpiod_get(struct device *dev, 141static inline struct gpio_desc *__must_check __gpiod_get(struct device *dev,
118 const char *con_id, 142 const char *con_id,
119 enum gpiod_flags flags) 143 enum gpiod_flags flags)
@@ -143,6 +167,20 @@ __gpiod_get_index_optional(struct device *dev, const char *con_id,
143 return ERR_PTR(-ENOSYS); 167 return ERR_PTR(-ENOSYS);
144} 168}
145 169
170static inline struct gpio_descs *__must_check
171gpiod_get_array(struct device *dev, const char *con_id,
172 enum gpiod_flags flags)
173{
174 return ERR_PTR(-ENOSYS);
175}
176
177static inline struct gpio_descs *__must_check
178gpiod_get_array_optional(struct device *dev, const char *con_id,
179 enum gpiod_flags flags)
180{
181 return ERR_PTR(-ENOSYS);
182}
183
146static inline void gpiod_put(struct gpio_desc *desc) 184static inline void gpiod_put(struct gpio_desc *desc)
147{ 185{
148 might_sleep(); 186 might_sleep();
@@ -151,6 +189,14 @@ static inline void gpiod_put(struct gpio_desc *desc)
151 WARN_ON(1); 189 WARN_ON(1);
152} 190}
153 191
192static inline void gpiod_put_array(struct gpio_descs *descs)
193{
194 might_sleep();
195
196 /* GPIO can never have been requested */
197 WARN_ON(1);
198}
199
154static inline struct gpio_desc *__must_check 200static inline struct gpio_desc *__must_check
155__devm_gpiod_get(struct device *dev, 201__devm_gpiod_get(struct device *dev,
156 const char *con_id, 202 const char *con_id,