blob: 3d7c90fe7189f66075454ffadef774d53806cc3f [file] [log] [blame]
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +09001#include <linux/idr.h>
2#include <linux/mutex.h>
3#include <linux/device.h>
4#include <linux/sysfs.h>
5#include <linux/gpio/consumer.h>
6#include <linux/gpio/driver.h>
7#include <linux/interrupt.h>
8#include <linux/kdev_t.h>
Johan Hovoldc43960f2015-05-04 17:10:37 +02009#include <linux/slab.h>
Christophe Leroy1efba35a2017-12-18 11:08:35 +010010#include <linux/ctype.h>
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +090011
12#include "gpiolib.h"
13
Johan Hovoldcef17172015-05-04 17:10:48 +020014#define GPIO_IRQF_TRIGGER_FALLING BIT(0)
15#define GPIO_IRQF_TRIGGER_RISING BIT(1)
16#define GPIO_IRQF_TRIGGER_BOTH (GPIO_IRQF_TRIGGER_FALLING | \
17 GPIO_IRQF_TRIGGER_RISING)
18
Johan Hovoldc43960f2015-05-04 17:10:37 +020019struct gpiod_data {
20 struct gpio_desc *desc;
Johan Hovold6ffcb792015-05-04 17:10:44 +020021
22 struct mutex mutex;
Johan Hovolda08f5c22015-05-04 17:10:39 +020023 struct kernfs_node *value_kn;
Johan Hovold2ec74a92015-05-04 17:10:41 +020024 int irq;
Johan Hovoldcef17172015-05-04 17:10:48 +020025 unsigned char irq_flags;
Johan Hovold427fdee2015-05-04 17:10:47 +020026
27 bool direction_can_change;
Johan Hovoldc43960f2015-05-04 17:10:37 +020028};
29
Johan Hovold6ffcb792015-05-04 17:10:44 +020030/*
31 * Lock to serialise gpiod export and unexport, and prevent re-export of
32 * gpiod whose chip is being unregistered.
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +090033 */
34static DEFINE_MUTEX(sysfs_lock);
35
36/*
37 * /sys/class/gpio/gpioN... only for GPIOs that are exported
38 * /direction
39 * * MAY BE OMITTED if kernel won't allow direction changes
40 * * is read/write as "in" or "out"
41 * * may also be written as "high" or "low", initializing
42 * output value as specified ("out" implies "low")
43 * /value
44 * * always readable, subject to hardware behavior
45 * * may be writable, as zero/nonzero
46 * /edge
47 * * configures behavior of poll(2) on /value
48 * * available only if pin can generate IRQs on input
49 * * is read/write as "none", "falling", "rising", or "both"
50 * /active_low
51 * * configures polarity of /value
52 * * is read/write as zero/nonzero
53 * * also affects existing and subsequent "falling" and "rising"
54 * /edge configuration
55 */
56
Johan Hovold6beac9d12015-05-04 17:10:34 +020057static ssize_t direction_show(struct device *dev,
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +090058 struct device_attribute *attr, char *buf)
59{
Johan Hovoldc43960f2015-05-04 17:10:37 +020060 struct gpiod_data *data = dev_get_drvdata(dev);
61 struct gpio_desc *desc = data->desc;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +090062 ssize_t status;
63
Johan Hovold6ffcb792015-05-04 17:10:44 +020064 mutex_lock(&data->mutex);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +090065
Johan Hovoldf0b78662015-05-04 17:10:36 +020066 gpiod_get_direction(desc);
67 status = sprintf(buf, "%s\n",
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +090068 test_bit(FLAG_IS_OUT, &desc->flags)
69 ? "out" : "in");
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +090070
Johan Hovold6ffcb792015-05-04 17:10:44 +020071 mutex_unlock(&data->mutex);
72
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +090073 return status;
74}
75
Johan Hovold6beac9d12015-05-04 17:10:34 +020076static ssize_t direction_store(struct device *dev,
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +090077 struct device_attribute *attr, const char *buf, size_t size)
78{
Johan Hovoldc43960f2015-05-04 17:10:37 +020079 struct gpiod_data *data = dev_get_drvdata(dev);
80 struct gpio_desc *desc = data->desc;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +090081 ssize_t status;
82
Johan Hovold6ffcb792015-05-04 17:10:44 +020083 mutex_lock(&data->mutex);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +090084
Johan Hovoldf0b78662015-05-04 17:10:36 +020085 if (sysfs_streq(buf, "high"))
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +090086 status = gpiod_direction_output_raw(desc, 1);
87 else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low"))
88 status = gpiod_direction_output_raw(desc, 0);
89 else if (sysfs_streq(buf, "in"))
90 status = gpiod_direction_input(desc);
91 else
92 status = -EINVAL;
93
Johan Hovold6ffcb792015-05-04 17:10:44 +020094 mutex_unlock(&data->mutex);
95
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +090096 return status ? : size;
97}
Johan Hovold6beac9d12015-05-04 17:10:34 +020098static DEVICE_ATTR_RW(direction);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +090099
Johan Hovold6beac9d12015-05-04 17:10:34 +0200100static ssize_t value_show(struct device *dev,
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900101 struct device_attribute *attr, char *buf)
102{
Johan Hovoldc43960f2015-05-04 17:10:37 +0200103 struct gpiod_data *data = dev_get_drvdata(dev);
104 struct gpio_desc *desc = data->desc;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900105 ssize_t status;
106
Johan Hovold6ffcb792015-05-04 17:10:44 +0200107 mutex_lock(&data->mutex);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900108
Christophe Leroy9295c012017-12-18 11:08:31 +0100109 status = gpiod_get_value_cansleep(desc);
110 if (status < 0)
111 goto err;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900112
Christophe Leroy7a94b882017-12-18 11:08:33 +0100113 buf[0] = '0' + status;
114 buf[1] = '\n';
115 status = 2;
Christophe Leroy9295c012017-12-18 11:08:31 +0100116err:
Johan Hovold6ffcb792015-05-04 17:10:44 +0200117 mutex_unlock(&data->mutex);
118
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900119 return status;
120}
121
Johan Hovold6beac9d12015-05-04 17:10:34 +0200122static ssize_t value_store(struct device *dev,
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900123 struct device_attribute *attr, const char *buf, size_t size)
124{
Johan Hovoldc43960f2015-05-04 17:10:37 +0200125 struct gpiod_data *data = dev_get_drvdata(dev);
126 struct gpio_desc *desc = data->desc;
Christophe Leroy1efba35a2017-12-18 11:08:35 +0100127 ssize_t status = 0;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900128
Johan Hovold6ffcb792015-05-04 17:10:44 +0200129 mutex_lock(&data->mutex);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900130
Johan Hovoldf0b78662015-05-04 17:10:36 +0200131 if (!test_bit(FLAG_IS_OUT, &desc->flags)) {
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900132 status = -EPERM;
Johan Hovoldf0b78662015-05-04 17:10:36 +0200133 } else {
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900134 long value;
135
Christophe Leroy1efba35a2017-12-18 11:08:35 +0100136 if (size <= 2 && isdigit(buf[0]) &&
137 (size == 1 || buf[1] == '\n'))
138 value = buf[0] - '0';
139 else
140 status = kstrtol(buf, 0, &value);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900141 if (status == 0) {
142 gpiod_set_value_cansleep(desc, value);
143 status = size;
144 }
145 }
146
Johan Hovold6ffcb792015-05-04 17:10:44 +0200147 mutex_unlock(&data->mutex);
148
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900149 return status;
150}
Christophe Leroy7fda9102017-12-18 11:08:29 +0100151static DEVICE_ATTR_PREALLOC(value, S_IWUSR | S_IRUGO, value_show, value_store);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900152
153static irqreturn_t gpio_sysfs_irq(int irq, void *priv)
154{
Johan Hovolda08f5c22015-05-04 17:10:39 +0200155 struct gpiod_data *data = priv;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900156
Johan Hovolda08f5c22015-05-04 17:10:39 +0200157 sysfs_notify_dirent(data->value_kn);
158
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900159 return IRQ_HANDLED;
160}
161
Johan Hovold6ffcb792015-05-04 17:10:44 +0200162/* Caller holds gpiod-data mutex. */
Johan Hovoldcef17172015-05-04 17:10:48 +0200163static int gpio_sysfs_request_irq(struct device *dev, unsigned char flags)
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900164{
Johan Hovold0f628502015-05-04 17:10:38 +0200165 struct gpiod_data *data = dev_get_drvdata(dev);
166 struct gpio_desc *desc = data->desc;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900167 unsigned long irq_flags;
Johan Hovold2ec74a92015-05-04 17:10:41 +0200168 int ret;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900169
Johan Hovold2ec74a92015-05-04 17:10:41 +0200170 data->irq = gpiod_to_irq(desc);
171 if (data->irq < 0)
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900172 return -EIO;
173
Johan Hovold2ec74a92015-05-04 17:10:41 +0200174 data->value_kn = sysfs_get_dirent(dev->kobj.sd, "value");
175 if (!data->value_kn)
176 return -ENODEV;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900177
178 irq_flags = IRQF_SHARED;
Johan Hovoldcef17172015-05-04 17:10:48 +0200179 if (flags & GPIO_IRQF_TRIGGER_FALLING)
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900180 irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
181 IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
Johan Hovoldcef17172015-05-04 17:10:48 +0200182 if (flags & GPIO_IRQF_TRIGGER_RISING)
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900183 irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
184 IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
185
Johan Hovold52176d02015-05-04 17:10:28 +0200186 /*
187 * FIXME: This should be done in the irq_request_resources callback
188 * when the irq is requested, but a few drivers currently fail
189 * to do so.
190 *
191 * Remove this redundant call (along with the corresponding
192 * unlock) when those drivers have been fixed.
193 */
Linus Walleijfdeb8e12016-02-10 10:57:36 +0100194 ret = gpiochip_lock_as_irq(desc->gdev->chip, gpio_chip_hwgpio(desc));
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900195 if (ret < 0)
Johan Hovold2ec74a92015-05-04 17:10:41 +0200196 goto err_put_kn;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900197
Johan Hovold2ec74a92015-05-04 17:10:41 +0200198 ret = request_any_context_irq(data->irq, gpio_sysfs_irq, irq_flags,
Johan Hovolda08f5c22015-05-04 17:10:39 +0200199 "gpiolib", data);
Johan Hovold52176d02015-05-04 17:10:28 +0200200 if (ret < 0)
201 goto err_unlock;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900202
Johan Hovoldcef17172015-05-04 17:10:48 +0200203 data->irq_flags = flags;
Johan Hovold2ec74a92015-05-04 17:10:41 +0200204
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900205 return 0;
206
Johan Hovold52176d02015-05-04 17:10:28 +0200207err_unlock:
Linus Walleijfdeb8e12016-02-10 10:57:36 +0100208 gpiochip_unlock_as_irq(desc->gdev->chip, gpio_chip_hwgpio(desc));
Johan Hovold2ec74a92015-05-04 17:10:41 +0200209err_put_kn:
210 sysfs_put(data->value_kn);
211
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900212 return ret;
213}
214
Johan Hovold6ffcb792015-05-04 17:10:44 +0200215/*
216 * Caller holds gpiod-data mutex (unless called after class-device
217 * deregistration).
218 */
Johan Hovold2ec74a92015-05-04 17:10:41 +0200219static void gpio_sysfs_free_irq(struct device *dev)
220{
221 struct gpiod_data *data = dev_get_drvdata(dev);
222 struct gpio_desc *desc = data->desc;
223
Johan Hovoldcef17172015-05-04 17:10:48 +0200224 data->irq_flags = 0;
Johan Hovold2ec74a92015-05-04 17:10:41 +0200225 free_irq(data->irq, data);
Linus Walleijfdeb8e12016-02-10 10:57:36 +0100226 gpiochip_unlock_as_irq(desc->gdev->chip, gpio_chip_hwgpio(desc));
Johan Hovold2ec74a92015-05-04 17:10:41 +0200227 sysfs_put(data->value_kn);
228}
229
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900230static const struct {
231 const char *name;
Johan Hovoldcef17172015-05-04 17:10:48 +0200232 unsigned char flags;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900233} trigger_types[] = {
234 { "none", 0 },
Johan Hovoldcef17172015-05-04 17:10:48 +0200235 { "falling", GPIO_IRQF_TRIGGER_FALLING },
236 { "rising", GPIO_IRQF_TRIGGER_RISING },
237 { "both", GPIO_IRQF_TRIGGER_BOTH },
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900238};
239
Johan Hovold6beac9d12015-05-04 17:10:34 +0200240static ssize_t edge_show(struct device *dev,
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900241 struct device_attribute *attr, char *buf)
242{
Johan Hovoldc43960f2015-05-04 17:10:37 +0200243 struct gpiod_data *data = dev_get_drvdata(dev);
Johan Hovoldf0b78662015-05-04 17:10:36 +0200244 ssize_t status = 0;
245 int i;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900246
Johan Hovold6ffcb792015-05-04 17:10:44 +0200247 mutex_lock(&data->mutex);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900248
Johan Hovoldf0b78662015-05-04 17:10:36 +0200249 for (i = 0; i < ARRAY_SIZE(trigger_types); i++) {
Johan Hovoldcef17172015-05-04 17:10:48 +0200250 if (data->irq_flags == trigger_types[i].flags) {
Johan Hovoldf0b78662015-05-04 17:10:36 +0200251 status = sprintf(buf, "%s\n", trigger_types[i].name);
252 break;
253 }
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900254 }
255
Johan Hovold6ffcb792015-05-04 17:10:44 +0200256 mutex_unlock(&data->mutex);
257
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900258 return status;
259}
260
Johan Hovold6beac9d12015-05-04 17:10:34 +0200261static ssize_t edge_store(struct device *dev,
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900262 struct device_attribute *attr, const char *buf, size_t size)
263{
Johan Hovoldb91e1802015-05-04 17:10:40 +0200264 struct gpiod_data *data = dev_get_drvdata(dev);
Johan Hovoldcef17172015-05-04 17:10:48 +0200265 unsigned char flags;
Johan Hovold2ec74a92015-05-04 17:10:41 +0200266 ssize_t status = size;
Johan Hovolde4339ce2015-05-04 17:10:42 +0200267 int i;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900268
Johan Hovolde4339ce2015-05-04 17:10:42 +0200269 for (i = 0; i < ARRAY_SIZE(trigger_types); i++) {
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900270 if (sysfs_streq(trigger_types[i].name, buf))
Johan Hovolde4339ce2015-05-04 17:10:42 +0200271 break;
272 }
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900273
Johan Hovolde4339ce2015-05-04 17:10:42 +0200274 if (i == ARRAY_SIZE(trigger_types))
275 return -EINVAL;
276
Johan Hovoldb91e1802015-05-04 17:10:40 +0200277 flags = trigger_types[i].flags;
278
Johan Hovold6ffcb792015-05-04 17:10:44 +0200279 mutex_lock(&data->mutex);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900280
Johan Hovoldcef17172015-05-04 17:10:48 +0200281 if (flags == data->irq_flags) {
Johan Hovoldb91e1802015-05-04 17:10:40 +0200282 status = size;
283 goto out_unlock;
284 }
285
Johan Hovoldcef17172015-05-04 17:10:48 +0200286 if (data->irq_flags)
Johan Hovold2ec74a92015-05-04 17:10:41 +0200287 gpio_sysfs_free_irq(dev);
288
289 if (flags) {
290 status = gpio_sysfs_request_irq(dev, flags);
291 if (!status)
292 status = size;
293 }
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900294
Johan Hovoldb91e1802015-05-04 17:10:40 +0200295out_unlock:
Johan Hovold6ffcb792015-05-04 17:10:44 +0200296 mutex_unlock(&data->mutex);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900297
298 return status;
299}
Johan Hovold6beac9d12015-05-04 17:10:34 +0200300static DEVICE_ATTR_RW(edge);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900301
Johan Hovold6ffcb792015-05-04 17:10:44 +0200302/* Caller holds gpiod-data mutex. */
Johan Hovold2f323b82015-05-04 17:10:46 +0200303static int gpio_sysfs_set_active_low(struct device *dev, int value)
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900304{
Johan Hovold0f628502015-05-04 17:10:38 +0200305 struct gpiod_data *data = dev_get_drvdata(dev);
306 struct gpio_desc *desc = data->desc;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900307 int status = 0;
Johan Hovoldcef17172015-05-04 17:10:48 +0200308 unsigned int flags = data->irq_flags;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900309
310 if (!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) == !!value)
311 return 0;
312
313 if (value)
314 set_bit(FLAG_ACTIVE_LOW, &desc->flags);
315 else
316 clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
317
318 /* reconfigure poll(2) support if enabled on one edge only */
Johan Hovoldcef17172015-05-04 17:10:48 +0200319 if (flags == GPIO_IRQF_TRIGGER_FALLING ||
320 flags == GPIO_IRQF_TRIGGER_RISING) {
Johan Hovold2ec74a92015-05-04 17:10:41 +0200321 gpio_sysfs_free_irq(dev);
Johan Hovoldcef17172015-05-04 17:10:48 +0200322 status = gpio_sysfs_request_irq(dev, flags);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900323 }
324
325 return status;
326}
327
Johan Hovold6beac9d12015-05-04 17:10:34 +0200328static ssize_t active_low_show(struct device *dev,
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900329 struct device_attribute *attr, char *buf)
330{
Johan Hovoldc43960f2015-05-04 17:10:37 +0200331 struct gpiod_data *data = dev_get_drvdata(dev);
332 struct gpio_desc *desc = data->desc;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900333 ssize_t status;
334
Johan Hovold6ffcb792015-05-04 17:10:44 +0200335 mutex_lock(&data->mutex);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900336
Johan Hovoldf0b78662015-05-04 17:10:36 +0200337 status = sprintf(buf, "%d\n",
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900338 !!test_bit(FLAG_ACTIVE_LOW, &desc->flags));
339
Johan Hovold6ffcb792015-05-04 17:10:44 +0200340 mutex_unlock(&data->mutex);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900341
342 return status;
343}
344
Johan Hovold6beac9d12015-05-04 17:10:34 +0200345static ssize_t active_low_store(struct device *dev,
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900346 struct device_attribute *attr, const char *buf, size_t size)
347{
Johan Hovold6ffcb792015-05-04 17:10:44 +0200348 struct gpiod_data *data = dev_get_drvdata(dev);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900349 ssize_t status;
Johan Hovoldf0b78662015-05-04 17:10:36 +0200350 long value;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900351
Johan Hovold6ffcb792015-05-04 17:10:44 +0200352 mutex_lock(&data->mutex);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900353
Johan Hovoldf0b78662015-05-04 17:10:36 +0200354 status = kstrtol(buf, 0, &value);
355 if (status == 0)
Johan Hovold2f323b82015-05-04 17:10:46 +0200356 status = gpio_sysfs_set_active_low(dev, value);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900357
Johan Hovold6ffcb792015-05-04 17:10:44 +0200358 mutex_unlock(&data->mutex);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900359
360 return status ? : size;
361}
Johan Hovold6beac9d12015-05-04 17:10:34 +0200362static DEVICE_ATTR_RW(active_low);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900363
Johan Hovoldebbeba12015-01-13 13:00:06 +0100364static umode_t gpio_is_visible(struct kobject *kobj, struct attribute *attr,
365 int n)
366{
367 struct device *dev = container_of(kobj, struct device, kobj);
Johan Hovoldc43960f2015-05-04 17:10:37 +0200368 struct gpiod_data *data = dev_get_drvdata(dev);
369 struct gpio_desc *desc = data->desc;
Johan Hovoldebbeba12015-01-13 13:00:06 +0100370 umode_t mode = attr->mode;
Johan Hovold427fdee2015-05-04 17:10:47 +0200371 bool show_direction = data->direction_can_change;
Johan Hovoldebbeba12015-01-13 13:00:06 +0100372
373 if (attr == &dev_attr_direction.attr) {
374 if (!show_direction)
375 mode = 0;
376 } else if (attr == &dev_attr_edge.attr) {
377 if (gpiod_to_irq(desc) < 0)
378 mode = 0;
379 if (!show_direction && test_bit(FLAG_IS_OUT, &desc->flags))
380 mode = 0;
381 }
382
383 return mode;
384}
385
Johan Hovold0915e6f2015-01-13 13:00:05 +0100386static struct attribute *gpio_attrs[] = {
Johan Hovoldebbeba12015-01-13 13:00:06 +0100387 &dev_attr_direction.attr,
388 &dev_attr_edge.attr,
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900389 &dev_attr_value.attr,
390 &dev_attr_active_low.attr,
391 NULL,
392};
Johan Hovoldebbeba12015-01-13 13:00:06 +0100393
394static const struct attribute_group gpio_group = {
395 .attrs = gpio_attrs,
396 .is_visible = gpio_is_visible,
397};
398
399static const struct attribute_group *gpio_groups[] = {
400 &gpio_group,
401 NULL
402};
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900403
404/*
405 * /sys/class/gpio/gpiochipN/
406 * /base ... matching gpio_chip.base (N)
407 * /label ... matching gpio_chip.label
408 * /ngpio ... matching gpio_chip.ngpio
409 */
410
Johan Hovold6beac9d12015-05-04 17:10:34 +0200411static ssize_t base_show(struct device *dev,
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900412 struct device_attribute *attr, char *buf)
413{
414 const struct gpio_chip *chip = dev_get_drvdata(dev);
415
416 return sprintf(buf, "%d\n", chip->base);
417}
Johan Hovold6beac9d12015-05-04 17:10:34 +0200418static DEVICE_ATTR_RO(base);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900419
Johan Hovold6beac9d12015-05-04 17:10:34 +0200420static ssize_t label_show(struct device *dev,
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900421 struct device_attribute *attr, char *buf)
422{
423 const struct gpio_chip *chip = dev_get_drvdata(dev);
424
425 return sprintf(buf, "%s\n", chip->label ? : "");
426}
Johan Hovold6beac9d12015-05-04 17:10:34 +0200427static DEVICE_ATTR_RO(label);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900428
Johan Hovold6beac9d12015-05-04 17:10:34 +0200429static ssize_t ngpio_show(struct device *dev,
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900430 struct device_attribute *attr, char *buf)
431{
432 const struct gpio_chip *chip = dev_get_drvdata(dev);
433
434 return sprintf(buf, "%u\n", chip->ngpio);
435}
Johan Hovold6beac9d12015-05-04 17:10:34 +0200436static DEVICE_ATTR_RO(ngpio);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900437
Johan Hovold121b6a72015-01-13 13:00:04 +0100438static struct attribute *gpiochip_attrs[] = {
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900439 &dev_attr_base.attr,
440 &dev_attr_label.attr,
441 &dev_attr_ngpio.attr,
442 NULL,
443};
Johan Hovold121b6a72015-01-13 13:00:04 +0100444ATTRIBUTE_GROUPS(gpiochip);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900445
446/*
447 * /sys/class/gpio/export ... write-only
448 * integer N ... number of GPIO to export (full access)
449 * /sys/class/gpio/unexport ... write-only
450 * integer N ... number of GPIO to unexport
451 */
452static ssize_t export_store(struct class *class,
453 struct class_attribute *attr,
454 const char *buf, size_t len)
455{
456 long gpio;
457 struct gpio_desc *desc;
458 int status;
459
460 status = kstrtol(buf, 0, &gpio);
461 if (status < 0)
462 goto done;
463
Linus Walleijf13a0b02018-09-13 14:05:26 +0200464 desc = gpio_to_desc(gpio);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900465 /* reject invalid GPIOs */
466 if (!desc) {
467 pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
468 return -EINVAL;
469 }
470
471 /* No extra locking here; FLAG_SYSFS just signifies that the
472 * request and export were done by on behalf of userspace, so
473 * they may be undone on its behalf too.
474 */
475
476 status = gpiod_request(desc, "sysfs");
477 if (status < 0) {
478 if (status == -EPROBE_DEFER)
479 status = -ENODEV;
480 goto done;
481 }
Andrew Jefferye10f72b2017-11-30 14:25:24 +1030482
483 status = gpiod_set_transitory(desc, false);
484 if (!status) {
485 status = gpiod_export(desc, true);
486 if (status < 0)
487 gpiod_free(desc);
488 else
489 set_bit(FLAG_SYSFS, &desc->flags);
490 }
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900491
492done:
493 if (status)
494 pr_debug("%s: status %d\n", __func__, status);
495 return status ? : len;
496}
Greg Kroah-Hartmand83bb152017-06-08 10:12:40 +0200497static CLASS_ATTR_WO(export);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900498
499static ssize_t unexport_store(struct class *class,
500 struct class_attribute *attr,
501 const char *buf, size_t len)
502{
503 long gpio;
504 struct gpio_desc *desc;
505 int status;
506
507 status = kstrtol(buf, 0, &gpio);
508 if (status < 0)
509 goto done;
510
Linus Walleijf13a0b02018-09-13 14:05:26 +0200511 desc = gpio_to_desc(gpio);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900512 /* reject bogus commands (gpio_unexport ignores them) */
513 if (!desc) {
514 pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
515 return -EINVAL;
516 }
517
518 status = -EINVAL;
519
520 /* No extra locking here; FLAG_SYSFS just signifies that the
521 * request and export were done by on behalf of userspace, so
522 * they may be undone on its behalf too.
523 */
524 if (test_and_clear_bit(FLAG_SYSFS, &desc->flags)) {
525 status = 0;
526 gpiod_free(desc);
527 }
528done:
529 if (status)
530 pr_debug("%s: status %d\n", __func__, status);
531 return status ? : len;
532}
Greg Kroah-Hartmand83bb152017-06-08 10:12:40 +0200533static CLASS_ATTR_WO(unexport);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900534
Greg Kroah-Hartmand83bb152017-06-08 10:12:40 +0200535static struct attribute *gpio_class_attrs[] = {
536 &class_attr_export.attr,
537 &class_attr_unexport.attr,
538 NULL,
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900539};
Greg Kroah-Hartmand83bb152017-06-08 10:12:40 +0200540ATTRIBUTE_GROUPS(gpio_class);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900541
542static struct class gpio_class = {
543 .name = "gpio",
544 .owner = THIS_MODULE,
545
Greg Kroah-Hartmand83bb152017-06-08 10:12:40 +0200546 .class_groups = gpio_class_groups,
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900547};
548
549
550/**
551 * gpiod_export - export a GPIO through sysfs
Thierry Reding2d9d0512017-07-24 16:57:26 +0200552 * @desc: GPIO to make available, already requested
553 * @direction_may_change: true if userspace may change GPIO direction
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900554 * Context: arch_initcall or later
555 *
556 * When drivers want to make a GPIO accessible to userspace after they
557 * have requested it -- perhaps while debugging, or as part of their
558 * public interface -- they may use this routine. If the GPIO can
559 * change direction (some can't) and the caller allows it, userspace
560 * will see "direction" sysfs attribute which may be used to change
561 * the gpio's direction. A "value" attribute will always be provided.
562 *
563 * Returns zero on success, else an error.
564 */
565int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
566{
Johan Hovold483d8212015-04-21 17:42:09 +0200567 struct gpio_chip *chip;
Linus Walleijff2b1352015-10-20 11:10:38 +0200568 struct gpio_device *gdev;
Johan Hovoldc43960f2015-05-04 17:10:37 +0200569 struct gpiod_data *data;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900570 unsigned long flags;
571 int status;
572 const char *ioname = NULL;
573 struct device *dev;
574 int offset;
575
576 /* can't export until sysfs is available ... */
577 if (!gpio_class.p) {
578 pr_debug("%s: called too early!\n", __func__);
579 return -ENOENT;
580 }
581
582 if (!desc) {
583 pr_debug("%s: invalid gpio descriptor\n", __func__);
584 return -EINVAL;
585 }
586
Linus Walleijfdeb8e12016-02-10 10:57:36 +0100587 gdev = desc->gdev;
588 chip = gdev->chip;
Johan Hovold483d8212015-04-21 17:42:09 +0200589
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900590 mutex_lock(&sysfs_lock);
591
Johan Hovold483d8212015-04-21 17:42:09 +0200592 /* check if chip is being removed */
Linus Walleijafbc4f32016-02-09 13:21:06 +0100593 if (!chip || !gdev->mockdev) {
Johan Hovold483d8212015-04-21 17:42:09 +0200594 status = -ENODEV;
Johan Hovoldc43960f2015-05-04 17:10:37 +0200595 goto err_unlock;
Johan Hovold483d8212015-04-21 17:42:09 +0200596 }
597
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900598 spin_lock_irqsave(&gpio_lock, flags);
599 if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
600 test_bit(FLAG_EXPORT, &desc->flags)) {
601 spin_unlock_irqrestore(&gpio_lock, flags);
602 gpiod_dbg(desc, "%s: unavailable (requested=%d, exported=%d)\n",
603 __func__,
604 test_bit(FLAG_REQUESTED, &desc->flags),
605 test_bit(FLAG_EXPORT, &desc->flags));
606 status = -EPERM;
Johan Hovoldc43960f2015-05-04 17:10:37 +0200607 goto err_unlock;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900608 }
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900609 spin_unlock_irqrestore(&gpio_lock, flags);
610
Johan Hovoldc43960f2015-05-04 17:10:37 +0200611 data = kzalloc(sizeof(*data), GFP_KERNEL);
612 if (!data) {
613 status = -ENOMEM;
614 goto err_unlock;
615 }
616
617 data->desc = desc;
Johan Hovold6ffcb792015-05-04 17:10:44 +0200618 mutex_init(&data->mutex);
Johan Hovold427fdee2015-05-04 17:10:47 +0200619 if (chip->direction_input && chip->direction_output)
620 data->direction_can_change = direction_may_change;
621 else
622 data->direction_can_change = false;
Johan Hovoldc43960f2015-05-04 17:10:37 +0200623
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900624 offset = gpio_chip_hwgpio(desc);
Johan Hovoldcecf58a2015-05-04 17:10:29 +0200625 if (chip->names && chip->names[offset])
626 ioname = chip->names[offset];
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900627
Linus Walleijff2b1352015-10-20 11:10:38 +0200628 dev = device_create_with_groups(&gpio_class, &gdev->dev,
Johan Hovoldc43960f2015-05-04 17:10:37 +0200629 MKDEV(0, 0), data, gpio_groups,
Johan Hovold0915e6f2015-01-13 13:00:05 +0100630 ioname ? ioname : "gpio%u",
631 desc_to_gpio(desc));
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900632 if (IS_ERR(dev)) {
633 status = PTR_ERR(dev);
Johan Hovoldc43960f2015-05-04 17:10:37 +0200634 goto err_free_data;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900635 }
636
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900637 set_bit(FLAG_EXPORT, &desc->flags);
638 mutex_unlock(&sysfs_lock);
639 return 0;
640
Johan Hovoldc43960f2015-05-04 17:10:37 +0200641err_free_data:
642 kfree(data);
643err_unlock:
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900644 mutex_unlock(&sysfs_lock);
645 gpiod_dbg(desc, "%s: status %d\n", __func__, status);
646 return status;
647}
648EXPORT_SYMBOL_GPL(gpiod_export);
649
Johan Hovoldc43960f2015-05-04 17:10:37 +0200650static int match_export(struct device *dev, const void *desc)
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900651{
Johan Hovoldc43960f2015-05-04 17:10:37 +0200652 struct gpiod_data *data = dev_get_drvdata(dev);
653
654 return data->desc == desc;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900655}
656
657/**
658 * gpiod_export_link - create a sysfs link to an exported GPIO node
659 * @dev: device under which to create symlink
660 * @name: name of the symlink
Thierry Reding2d9d0512017-07-24 16:57:26 +0200661 * @desc: GPIO to create symlink to, already exported
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900662 *
663 * Set up a symlink from /sys/.../dev/name to /sys/class/gpio/gpioN
664 * node. Caller is responsible for unlinking.
665 *
666 * Returns zero on success, else an error.
667 */
668int gpiod_export_link(struct device *dev, const char *name,
669 struct gpio_desc *desc)
670{
Johan Hovold56d30ec2015-05-04 17:10:43 +0200671 struct device *cdev;
672 int ret;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900673
674 if (!desc) {
675 pr_warn("%s: invalid GPIO\n", __func__);
676 return -EINVAL;
677 }
678
Johan Hovold56d30ec2015-05-04 17:10:43 +0200679 cdev = class_find_device(&gpio_class, NULL, desc, match_export);
680 if (!cdev)
681 return -ENODEV;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900682
Johan Hovold56d30ec2015-05-04 17:10:43 +0200683 ret = sysfs_create_link(&dev->kobj, &cdev->kobj, name);
684 put_device(cdev);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900685
Johan Hovold56d30ec2015-05-04 17:10:43 +0200686 return ret;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900687}
688EXPORT_SYMBOL_GPL(gpiod_export_link);
689
690/**
Amitesh Singh31963eb2016-09-08 17:11:20 +0530691 * gpiod_unexport - reverse effect of gpiod_export()
Thierry Reding2d9d0512017-07-24 16:57:26 +0200692 * @desc: GPIO to make unavailable
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900693 *
Amitesh Singh31963eb2016-09-08 17:11:20 +0530694 * This is implicit on gpiod_free().
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900695 */
696void gpiod_unexport(struct gpio_desc *desc)
697{
Johan Hovold72eba6f2015-05-04 17:10:45 +0200698 struct gpiod_data *data;
699 struct device *dev;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900700
701 if (!desc) {
702 pr_warn("%s: invalid GPIO\n", __func__);
703 return;
704 }
705
706 mutex_lock(&sysfs_lock);
707
Johan Hovold72eba6f2015-05-04 17:10:45 +0200708 if (!test_bit(FLAG_EXPORT, &desc->flags))
709 goto err_unlock;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900710
Johan Hovold72eba6f2015-05-04 17:10:45 +0200711 dev = class_find_device(&gpio_class, NULL, desc, match_export);
712 if (!dev)
713 goto err_unlock;
714
715 data = dev_get_drvdata(dev);
716
Johan Hovold72eba6f2015-05-04 17:10:45 +0200717 clear_bit(FLAG_EXPORT, &desc->flags);
718
719 device_unregister(dev);
720
721 /*
722 * Release irq after deregistration to prevent race with edge_store.
723 */
Johan Hovoldcef17172015-05-04 17:10:48 +0200724 if (data->irq_flags)
Johan Hovold72eba6f2015-05-04 17:10:45 +0200725 gpio_sysfs_free_irq(dev);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900726
727 mutex_unlock(&sysfs_lock);
728
Johan Hovold72eba6f2015-05-04 17:10:45 +0200729 put_device(dev);
730 kfree(data);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900731
Johan Hovold72eba6f2015-05-04 17:10:45 +0200732 return;
733
734err_unlock:
735 mutex_unlock(&sysfs_lock);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900736}
737EXPORT_SYMBOL_GPL(gpiod_unexport);
738
Linus Walleijafbc4f32016-02-09 13:21:06 +0100739int gpiochip_sysfs_register(struct gpio_device *gdev)
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900740{
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900741 struct device *dev;
Bamvor Jian Zhangd27c1722016-02-24 22:17:19 +0800742 struct device *parent;
Linus Walleijafbc4f32016-02-09 13:21:06 +0100743 struct gpio_chip *chip = gdev->chip;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900744
Johan Hovold426577b2015-05-04 17:10:32 +0200745 /*
746 * Many systems add gpio chips for SOC support very early,
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900747 * before driver model support is available. In those cases we
Johan Hovold426577b2015-05-04 17:10:32 +0200748 * register later, in gpiolib_sysfs_init() ... here we just
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900749 * verify that _some_ field of gpio_class got initialized.
750 */
751 if (!gpio_class.p)
752 return 0;
753
Bamvor Jian Zhangd27c1722016-02-24 22:17:19 +0800754 /*
755 * For sysfs backward compatibility we need to preserve this
756 * preferred parenting to the gpio_chip parent field, if set.
757 */
758 if (chip->parent)
759 parent = chip->parent;
760 else
761 parent = &gdev->dev;
762
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900763 /* use chip->base for the ID; it's already known to be unique */
Bamvor Jian Zhangd27c1722016-02-24 22:17:19 +0800764 dev = device_create_with_groups(&gpio_class, parent,
Linus Walleij58383c782015-11-04 09:56:26 +0100765 MKDEV(0, 0),
Johan Hovold121b6a72015-01-13 13:00:04 +0100766 chip, gpiochip_groups,
767 "gpiochip%d", chip->base);
768 if (IS_ERR(dev))
Johan Hovold6a4b6b02015-05-04 17:10:31 +0200769 return PTR_ERR(dev);
Johan Hovold3ff74be2015-05-04 17:10:30 +0200770
771 mutex_lock(&sysfs_lock);
Linus Walleijafbc4f32016-02-09 13:21:06 +0100772 gdev->mockdev = dev;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900773 mutex_unlock(&sysfs_lock);
774
Johan Hovold6a4b6b02015-05-04 17:10:31 +0200775 return 0;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900776}
777
Linus Walleijafbc4f32016-02-09 13:21:06 +0100778void gpiochip_sysfs_unregister(struct gpio_device *gdev)
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900779{
Johan Hovold483d8212015-04-21 17:42:09 +0200780 struct gpio_desc *desc;
Linus Walleijafbc4f32016-02-09 13:21:06 +0100781 struct gpio_chip *chip = gdev->chip;
Johan Hovold483d8212015-04-21 17:42:09 +0200782 unsigned int i;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900783
Linus Walleijafbc4f32016-02-09 13:21:06 +0100784 if (!gdev->mockdev)
Johan Hovold6a4b6b02015-05-04 17:10:31 +0200785 return;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900786
Linus Walleijafbc4f32016-02-09 13:21:06 +0100787 device_unregister(gdev->mockdev);
Johan Hovold6a4b6b02015-05-04 17:10:31 +0200788
789 /* prevent further gpiod exports */
790 mutex_lock(&sysfs_lock);
Linus Walleijafbc4f32016-02-09 13:21:06 +0100791 gdev->mockdev = NULL;
Johan Hovold6a4b6b02015-05-04 17:10:31 +0200792 mutex_unlock(&sysfs_lock);
Johan Hovold483d8212015-04-21 17:42:09 +0200793
794 /* unregister gpiod class devices owned by sysfs */
795 for (i = 0; i < chip->ngpio; i++) {
Linus Walleijfdeb8e12016-02-10 10:57:36 +0100796 desc = &gdev->descs[i];
Johan Hovold483d8212015-04-21 17:42:09 +0200797 if (test_and_clear_bit(FLAG_SYSFS, &desc->flags))
798 gpiod_free(desc);
799 }
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900800}
801
802static int __init gpiolib_sysfs_init(void)
803{
804 int status;
805 unsigned long flags;
Linus Walleijff2b1352015-10-20 11:10:38 +0200806 struct gpio_device *gdev;
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900807
808 status = class_register(&gpio_class);
809 if (status < 0)
810 return status;
811
812 /* Scan and register the gpio_chips which registered very
813 * early (e.g. before the class_register above was called).
814 *
815 * We run before arch_initcall() so chip->dev nodes can have
816 * registered, and so arch_initcall() can always gpio_export().
817 */
818 spin_lock_irqsave(&gpio_lock, flags);
Linus Walleijff2b1352015-10-20 11:10:38 +0200819 list_for_each_entry(gdev, &gpio_devices, list) {
Linus Walleijafbc4f32016-02-09 13:21:06 +0100820 if (gdev->mockdev)
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900821 continue;
822
Alexandre Courbot14141a92014-07-22 16:17:40 +0900823 /*
Johan Hovold426577b2015-05-04 17:10:32 +0200824 * TODO we yield gpio_lock here because
825 * gpiochip_sysfs_register() acquires a mutex. This is unsafe
826 * and needs to be fixed.
Alexandre Courbot14141a92014-07-22 16:17:40 +0900827 *
828 * Also it would be nice to use gpiochip_find() here so we
829 * can keep gpio_chips local to gpiolib.c, but the yield of
830 * gpio_lock prevents us from doing this.
831 */
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900832 spin_unlock_irqrestore(&gpio_lock, flags);
Linus Walleijafbc4f32016-02-09 13:21:06 +0100833 status = gpiochip_sysfs_register(gdev);
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900834 spin_lock_irqsave(&gpio_lock, flags);
835 }
836 spin_unlock_irqrestore(&gpio_lock, flags);
837
Alexandre Courbot0eb4c6c2014-07-01 14:45:15 +0900838 return status;
839}
840postcore_initcall(gpiolib_sysfs_init);