aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/devres.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-04-18 08:22:10 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-18 08:22:10 -0400
commit510965dd4a0a59504ba38455f77339ea8b4c6a70 (patch)
tree36492629ac68de94457482562660154f28e9e039 /drivers/gpio/devres.c
parent40d7839879b4584f91522d841afb22ed401cf40f (diff)
parent03daa6f82f2b634019fe8261698f6af3c133497f (diff)
Merge tag 'gpio-v4.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO updates from Linus Walleij: "This is the bulk of GPIO changes for the v4.1 development cycle: - A new GPIO hogging mechanism has been added. This can be used on boards that want to drive some GPIO line high, low, or set it as input on boot and then never touch it again. For some embedded systems this is bliss and simplifies things to a great extent. - Some API cleanup and closure: gpiod_get_array() and gpiod_put_array() has been added to get and put GPIOs in bulk as was possible with the non-descriptor API. - Encapsulate cross-calls to the pin control subsystem in <linux/gpio/driver.h>. Now this should be the only header any GPIO driver needs to include or something is wrong. Cleanups restricting drivers to this include are welcomed if tested. - Sort the GPIO Kconfig and split it into submenus, as it was becoming and unstructured, illogical and unnavigatable mess. I hope this is easier to follow. Menus that require a certain subsystem like I2C can now be hidden nicely for example, still working on others. - New drivers: - New driver for the Altera Soft GPIO. - The F7188x driver now handles the F71869 and F71869A variants. - The MIPS Loongson driver has been moved to drivers/gpio for consolidation and cleanup. - Cleanups: - The MAX732x is converted to use the GPIOLIB_IRQCHIP infrastructure. - The PCF857x is converted to use the GPIOLIB_IRQCHIP infrastructure. - Radical cleanup of the OMAP driver. - Misc: - Enable the DWAPB GPIO for all architectures. This is a "hard IP" block from Synopsys which has started to turn up in so diverse architectures as X86 Quark, ARC and a slew of ARM systems. So even though it's not an expander, it's generic enough to be available for all. - We add a mock GPIO on Crystalcove PMIC after a long discussion with Daniel Vetter et al, tracing back to the shootout at the kernel summit where DRM drivers and sub-componentization was discussed. In this case a mock GPIO is assumed to be the best compromise gaining some reuse of infrastructure without making DRM drivers overly complex at the same time. Let's see" * tag 'gpio-v4.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (62 commits) Revert "gpio: sch: use uapi/linux/pci_ids.h directly" gpio: dwapb: remove dependencies gpio: dwapb: enable for ARC gpio: removing kfree remove functionality gpio: mvebu: Fix mask/unmask managment per irq chip type gpio: split GPIO drivers in submenus gpio: move MFD GPIO drivers under their own comment gpio: move BCM Kona Kconfig option gpio: arrange SPI Kconfig symbols alphabetically gpio: arrange PCI GPIO controllers alphabetically gpio: arrange I2C Kconfig symbols alphabetically gpio: arrange Kconfig symbols alphabetically gpio: ich: Implement get_direction function gpio: use (!foo) instead of (foo == NULL) gpio: arizona: drop owner assignment from platform_drivers gpio: max7300: remove 'ret' variable gpio: use devm_kzalloc gpio: sch: use uapi/linux/pci_ids.h directly gpio: x-gene: fix devm_ioremap_resource() check gpio: loongson: Add Loongson-3A/3B GPIO driver support ...
Diffstat (limited to 'drivers/gpio/devres.c')
-rw-r--r--drivers/gpio/devres.c107
1 files changed, 106 insertions, 1 deletions
diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c
index 13dbd3dfc33a..07ba82317ece 100644
--- a/drivers/gpio/devres.c
+++ b/drivers/gpio/devres.c
@@ -35,6 +35,20 @@ static int devm_gpiod_match(struct device *dev, void *res, void *data)
35 return *this == *gpio; 35 return *this == *gpio;
36} 36}
37 37
38static void devm_gpiod_release_array(struct device *dev, void *res)
39{
40 struct gpio_descs **descs = res;
41
42 gpiod_put_array(*descs);
43}
44
45static int devm_gpiod_match_array(struct device *dev, void *res, void *data)
46{
47 struct gpio_descs **this = res, **gpios = data;
48
49 return *this == *gpios;
50}
51
38/** 52/**
39 * devm_gpiod_get - Resource-managed gpiod_get() 53 * devm_gpiod_get - Resource-managed gpiod_get()
40 * @dev: GPIO consumer 54 * @dev: GPIO consumer
@@ -111,23 +125,39 @@ EXPORT_SYMBOL(__devm_gpiod_get_index);
111/** 125/**
112 * devm_get_gpiod_from_child - get a GPIO descriptor from a device's child node 126 * devm_get_gpiod_from_child - get a GPIO descriptor from a device's child node
113 * @dev: GPIO consumer 127 * @dev: GPIO consumer
128 * @con_id: function within the GPIO consumer
114 * @child: firmware node (child of @dev) 129 * @child: firmware node (child of @dev)
115 * 130 *
116 * GPIO descriptors returned from this function are automatically disposed on 131 * GPIO descriptors returned from this function are automatically disposed on
117 * driver detach. 132 * driver detach.
118 */ 133 */
119struct gpio_desc *devm_get_gpiod_from_child(struct device *dev, 134struct gpio_desc *devm_get_gpiod_from_child(struct device *dev,
135 const char *con_id,
120 struct fwnode_handle *child) 136 struct fwnode_handle *child)
121{ 137{
138 static const char * const suffixes[] = { "gpios", "gpio" };
139 char prop_name[32]; /* 32 is max size of property name */
122 struct gpio_desc **dr; 140 struct gpio_desc **dr;
123 struct gpio_desc *desc; 141 struct gpio_desc *desc;
142 unsigned int i;
124 143
125 dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *), 144 dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
126 GFP_KERNEL); 145 GFP_KERNEL);
127 if (!dr) 146 if (!dr)
128 return ERR_PTR(-ENOMEM); 147 return ERR_PTR(-ENOMEM);
129 148
130 desc = fwnode_get_named_gpiod(child, "gpios"); 149 for (i = 0; i < ARRAY_SIZE(suffixes); i++) {
150 if (con_id)
151 snprintf(prop_name, sizeof(prop_name), "%s-%s",
152 con_id, suffixes[i]);
153 else
154 snprintf(prop_name, sizeof(prop_name), "%s",
155 suffixes[i]);
156
157 desc = fwnode_get_named_gpiod(child, prop_name);
158 if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER))
159 break;
160 }
131 if (IS_ERR(desc)) { 161 if (IS_ERR(desc)) {
132 devres_free(dr); 162 devres_free(dr);
133 return desc; 163 return desc;
@@ -170,6 +200,66 @@ struct gpio_desc *__must_check __devm_gpiod_get_index_optional(struct device *de
170EXPORT_SYMBOL(__devm_gpiod_get_index_optional); 200EXPORT_SYMBOL(__devm_gpiod_get_index_optional);
171 201
172/** 202/**
203 * devm_gpiod_get_array - Resource-managed gpiod_get_array()
204 * @dev: GPIO consumer
205 * @con_id: function within the GPIO consumer
206 * @flags: optional GPIO initialization flags
207 *
208 * Managed gpiod_get_array(). GPIO descriptors returned from this function are
209 * automatically disposed on driver detach. See gpiod_get_array() for detailed
210 * information about behavior and return values.
211 */
212struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev,
213 const char *con_id,
214 enum gpiod_flags flags)
215{
216 struct gpio_descs **dr;
217 struct gpio_descs *descs;
218
219 dr = devres_alloc(devm_gpiod_release_array,
220 sizeof(struct gpio_descs *), GFP_KERNEL);
221 if (!dr)
222 return ERR_PTR(-ENOMEM);
223
224 descs = gpiod_get_array(dev, con_id, flags);
225 if (IS_ERR(descs)) {
226 devres_free(dr);
227 return descs;
228 }
229
230 *dr = descs;
231 devres_add(dev, dr);
232
233 return descs;
234}
235EXPORT_SYMBOL(devm_gpiod_get_array);
236
237/**
238 * devm_gpiod_get_array_optional - Resource-managed gpiod_get_array_optional()
239 * @dev: GPIO consumer
240 * @con_id: function within the GPIO consumer
241 * @flags: optional GPIO initialization flags
242 *
243 * Managed gpiod_get_array_optional(). GPIO descriptors returned from this
244 * function are automatically disposed on driver detach.
245 * See gpiod_get_array_optional() for detailed information about behavior and
246 * return values.
247 */
248struct gpio_descs *__must_check
249devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
250 enum gpiod_flags flags)
251{
252 struct gpio_descs *descs;
253
254 descs = devm_gpiod_get_array(dev, con_id, flags);
255 if (IS_ERR(descs) && (PTR_ERR(descs) == -ENOENT))
256 return NULL;
257
258 return descs;
259}
260EXPORT_SYMBOL(devm_gpiod_get_array_optional);
261
262/**
173 * devm_gpiod_put - Resource-managed gpiod_put() 263 * devm_gpiod_put - Resource-managed gpiod_put()
174 * @desc: GPIO descriptor to dispose of 264 * @desc: GPIO descriptor to dispose of
175 * 265 *
@@ -184,6 +274,21 @@ void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
184} 274}
185EXPORT_SYMBOL(devm_gpiod_put); 275EXPORT_SYMBOL(devm_gpiod_put);
186 276
277/**
278 * devm_gpiod_put_array - Resource-managed gpiod_put_array()
279 * @descs: GPIO descriptor array to dispose of
280 *
281 * Dispose of an array of GPIO descriptors obtained with devm_gpiod_get_array().
282 * Normally this function will not be called as the GPIOs will be disposed of
283 * by the resource management code.
284 */
285void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs)
286{
287 WARN_ON(devres_release(dev, devm_gpiod_release_array,
288 devm_gpiod_match_array, &descs));
289}
290EXPORT_SYMBOL(devm_gpiod_put_array);
291
187 292
188 293
189 294