Commit | Line | Data |
---|---|---|
dae5f0af | 1 | // SPDX-License-Identifier: GPL-2.0 |
380c7ba3 AS |
2 | |
3 | #include <linux/bitops.h> | |
59cba4a0 | 4 | #include <linux/cleanup.h> |
380c7ba3 | 5 | #include <linux/device.h> |
380c7ba3 AS |
6 | #include <linux/init.h> |
7 | #include <linux/interrupt.h> | |
8 | #include <linux/kdev_t.h> | |
9 | #include <linux/kstrtox.h> | |
10 | #include <linux/list.h> | |
0eb4c6c2 | 11 | #include <linux/mutex.h> |
380c7ba3 AS |
12 | #include <linux/printk.h> |
13 | #include <linux/slab.h> | |
380c7ba3 | 14 | #include <linux/string.h> |
d82b9e08 | 15 | #include <linux/srcu.h> |
0eb4c6c2 | 16 | #include <linux/sysfs.h> |
380c7ba3 AS |
17 | #include <linux/types.h> |
18 | ||
0eb4c6c2 AC |
19 | #include <linux/gpio/consumer.h> |
20 | #include <linux/gpio/driver.h> | |
0eb4c6c2 | 21 | |
285678c9 BG |
22 | #include <uapi/linux/gpio.h> |
23 | ||
0eb4c6c2 | 24 | #include "gpiolib.h" |
ef087d8e | 25 | #include "gpiolib-sysfs.h" |
0eb4c6c2 | 26 | |
e69c6db4 BG |
27 | #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) |
28 | ||
380c7ba3 AS |
29 | struct kernfs_node; |
30 | ||
667630ed | 31 | #define GPIO_IRQF_TRIGGER_NONE 0 |
cef1717b JH |
32 | #define GPIO_IRQF_TRIGGER_FALLING BIT(0) |
33 | #define GPIO_IRQF_TRIGGER_RISING BIT(1) | |
34 | #define GPIO_IRQF_TRIGGER_BOTH (GPIO_IRQF_TRIGGER_FALLING | \ | |
35 | GPIO_IRQF_TRIGGER_RISING) | |
36 | ||
f7d4fb62 BG |
37 | enum { |
38 | GPIO_SYSFS_LINE_CLASS_ATTR_DIRECTION = 0, | |
39 | GPIO_SYSFS_LINE_CLASS_ATTR_VALUE, | |
40 | GPIO_SYSFS_LINE_CLASS_ATTR_EDGE, | |
41 | GPIO_SYSFS_LINE_CLASS_ATTR_ACTIVE_LOW, | |
42 | GPIO_SYSFS_LINE_CLASS_ATTR_SENTINEL, | |
43 | GPIO_SYSFS_LINE_CLASS_ATTR_SIZE, | |
44 | }; | |
45 | ||
e69c6db4 BG |
46 | #endif /* CONFIG_GPIO_SYSFS_LEGACY */ |
47 | ||
4fa93223 BG |
48 | enum { |
49 | GPIO_SYSFS_LINE_CHIP_ATTR_DIRECTION = 0, | |
50 | GPIO_SYSFS_LINE_CHIP_ATTR_VALUE, | |
51 | GPIO_SYSFS_LINE_CHIP_ATTR_SENTINEL, | |
52 | GPIO_SYSFS_LINE_CHIP_ATTR_SIZE, | |
53 | }; | |
54 | ||
c43960fb | 55 | struct gpiod_data { |
1cd53df7 BG |
56 | struct list_head list; |
57 | ||
c43960fb | 58 | struct gpio_desc *desc; |
1cd53df7 | 59 | struct device *dev; |
6ffcb797 JH |
60 | |
61 | struct mutex mutex; | |
e69c6db4 | 62 | #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) |
a08f5c21 | 63 | struct kernfs_node *value_kn; |
2ec74a95 | 64 | int irq; |
cef1717b | 65 | unsigned char irq_flags; |
e69c6db4 | 66 | #endif /* CONFIG_GPIO_SYSFS_LEGACY */ |
427fdeef JH |
67 | |
68 | bool direction_can_change; | |
f7d4fb62 | 69 | |
4fa93223 | 70 | struct kobject *parent; |
f7d4fb62 BG |
71 | struct device_attribute dir_attr; |
72 | struct device_attribute val_attr; | |
e69c6db4 BG |
73 | |
74 | #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) | |
f7d4fb62 BG |
75 | struct device_attribute edge_attr; |
76 | struct device_attribute active_low_attr; | |
77 | ||
78 | struct attribute *class_attrs[GPIO_SYSFS_LINE_CLASS_ATTR_SIZE]; | |
79 | struct attribute_group class_attr_group; | |
80 | const struct attribute_group *class_attr_groups[2]; | |
e69c6db4 | 81 | #endif /* CONFIG_GPIO_SYSFS_LEGACY */ |
4fa93223 BG |
82 | |
83 | struct attribute *chip_attrs[GPIO_SYSFS_LINE_CHIP_ATTR_SIZE]; | |
84 | struct attribute_group chip_attr_group; | |
85 | const struct attribute_group *chip_attr_groups[2]; | |
c43960fb JH |
86 | }; |
87 | ||
fd197928 | 88 | struct gpiodev_data { |
1cd53df7 | 89 | struct list_head exported_lines; |
fd197928 | 90 | struct gpio_device *gdev; |
2028f854 | 91 | struct device *cdev_id; /* Class device by GPIO device ID */ |
e69c6db4 | 92 | #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) |
fd197928 | 93 | struct device *cdev_base; /* Class device by GPIO base */ |
e69c6db4 | 94 | #endif /* CONFIG_GPIO_SYSFS_LEGACY */ |
fd197928 BG |
95 | }; |
96 | ||
6ffcb797 JH |
97 | /* |
98 | * Lock to serialise gpiod export and unexport, and prevent re-export of | |
99 | * gpiod whose chip is being unregistered. | |
0eb4c6c2 AC |
100 | */ |
101 | static DEFINE_MUTEX(sysfs_lock); | |
102 | ||
103 | /* | |
104 | * /sys/class/gpio/gpioN... only for GPIOs that are exported | |
105 | * /direction | |
106 | * * MAY BE OMITTED if kernel won't allow direction changes | |
107 | * * is read/write as "in" or "out" | |
108 | * * may also be written as "high" or "low", initializing | |
109 | * output value as specified ("out" implies "low") | |
110 | * /value | |
111 | * * always readable, subject to hardware behavior | |
112 | * * may be writable, as zero/nonzero | |
113 | * /edge | |
114 | * * configures behavior of poll(2) on /value | |
115 | * * available only if pin can generate IRQs on input | |
116 | * * is read/write as "none", "falling", "rising", or "both" | |
117 | * /active_low | |
118 | * * configures polarity of /value | |
119 | * * is read/write as zero/nonzero | |
120 | * * also affects existing and subsequent "falling" and "rising" | |
121 | * /edge configuration | |
122 | */ | |
123 | ||
6beac9d1 | 124 | static ssize_t direction_show(struct device *dev, |
dc665b52 | 125 | struct device_attribute *attr, char *buf) |
0eb4c6c2 | 126 | { |
f7d4fb62 BG |
127 | struct gpiod_data *data = container_of(attr, struct gpiod_data, |
128 | dir_attr); | |
c43960fb | 129 | struct gpio_desc *desc = data->desc; |
e28747da | 130 | int value; |
0eb4c6c2 | 131 | |
d99c980c BG |
132 | scoped_guard(mutex, &data->mutex) { |
133 | gpiod_get_direction(desc); | |
134 | value = !!test_bit(FLAG_IS_OUT, &desc->flags); | |
135 | } | |
6ffcb797 | 136 | |
e28747da | 137 | return sysfs_emit(buf, "%s\n", value ? "out" : "in"); |
0eb4c6c2 AC |
138 | } |
139 | ||
6beac9d1 | 140 | static ssize_t direction_store(struct device *dev, |
dc665b52 BG |
141 | struct device_attribute *attr, const char *buf, |
142 | size_t size) | |
0eb4c6c2 | 143 | { |
f7d4fb62 BG |
144 | struct gpiod_data *data = container_of(attr, struct gpiod_data, |
145 | dir_attr); | |
c43960fb | 146 | struct gpio_desc *desc = data->desc; |
dc665b52 | 147 | ssize_t status; |
0eb4c6c2 | 148 | |
d99c980c | 149 | guard(mutex)(&data->mutex); |
0eb4c6c2 | 150 | |
f0b7866a | 151 | if (sysfs_streq(buf, "high")) |
0eb4c6c2 AC |
152 | status = gpiod_direction_output_raw(desc, 1); |
153 | else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low")) | |
154 | status = gpiod_direction_output_raw(desc, 0); | |
155 | else if (sysfs_streq(buf, "in")) | |
156 | status = gpiod_direction_input(desc); | |
157 | else | |
158 | status = -EINVAL; | |
159 | ||
0eb4c6c2 AC |
160 | return status ? : size; |
161 | } | |
162 | ||
dc665b52 BG |
163 | static ssize_t value_show(struct device *dev, struct device_attribute *attr, |
164 | char *buf) | |
0eb4c6c2 | 165 | { |
f7d4fb62 BG |
166 | struct gpiod_data *data = container_of(attr, struct gpiod_data, |
167 | val_attr); | |
c43960fb | 168 | struct gpio_desc *desc = data->desc; |
dc665b52 | 169 | ssize_t status; |
0eb4c6c2 | 170 | |
d99c980c BG |
171 | scoped_guard(mutex, &data->mutex) |
172 | status = gpiod_get_value_cansleep(desc); | |
6ffcb797 | 173 | |
e28747da AS |
174 | if (status < 0) |
175 | return status; | |
176 | ||
177 | return sysfs_emit(buf, "%zd\n", status); | |
0eb4c6c2 AC |
178 | } |
179 | ||
dc665b52 BG |
180 | static ssize_t value_store(struct device *dev, struct device_attribute *attr, |
181 | const char *buf, size_t size) | |
0eb4c6c2 | 182 | { |
f7d4fb62 BG |
183 | struct gpiod_data *data = container_of(attr, struct gpiod_data, |
184 | val_attr); | |
c43960fb | 185 | struct gpio_desc *desc = data->desc; |
6b3c1791 AS |
186 | ssize_t status; |
187 | long value; | |
188 | ||
189 | status = kstrtol(buf, 0, &value); | |
92ac7de3 BG |
190 | if (status) |
191 | return status; | |
0eb4c6c2 | 192 | |
d99c980c | 193 | guard(mutex)(&data->mutex); |
0eb4c6c2 | 194 | |
92ac7de3 | 195 | status = gpiod_set_value_cansleep(desc, value); |
d99c980c BG |
196 | if (status) |
197 | return status; | |
0eb4c6c2 | 198 | |
d99c980c | 199 | return size; |
0eb4c6c2 | 200 | } |
0eb4c6c2 | 201 | |
e69c6db4 | 202 | #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) |
0eb4c6c2 AC |
203 | static irqreturn_t gpio_sysfs_irq(int irq, void *priv) |
204 | { | |
a08f5c21 JH |
205 | struct gpiod_data *data = priv; |
206 | ||
207 | sysfs_notify_dirent(data->value_kn); | |
0eb4c6c2 | 208 | |
0eb4c6c2 AC |
209 | return IRQ_HANDLED; |
210 | } | |
211 | ||
6ffcb797 | 212 | /* Caller holds gpiod-data mutex. */ |
7c49c129 | 213 | static int gpio_sysfs_request_irq(struct gpiod_data *data, unsigned char flags) |
0eb4c6c2 | 214 | { |
513246a3 BG |
215 | struct gpio_desc *desc = data->desc; |
216 | unsigned long irq_flags; | |
217 | int ret; | |
0eb4c6c2 | 218 | |
d83cee3d BG |
219 | CLASS(gpio_chip_guard, guard)(desc); |
220 | if (!guard.gc) | |
221 | return -ENODEV; | |
222 | ||
2ec74a95 JH |
223 | data->irq = gpiod_to_irq(desc); |
224 | if (data->irq < 0) | |
0eb4c6c2 AC |
225 | return -EIO; |
226 | ||
0eb4c6c2 | 227 | irq_flags = IRQF_SHARED; |
7b925098 | 228 | if (flags & GPIO_IRQF_TRIGGER_FALLING) { |
0eb4c6c2 | 229 | irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? |
dc665b52 | 230 | IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING; |
7b925098 BG |
231 | set_bit(FLAG_EDGE_FALLING, &desc->flags); |
232 | } | |
233 | if (flags & GPIO_IRQF_TRIGGER_RISING) { | |
0eb4c6c2 | 234 | irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? |
dc665b52 | 235 | IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; |
7b925098 BG |
236 | set_bit(FLAG_EDGE_RISING, &desc->flags); |
237 | } | |
0eb4c6c2 | 238 | |
52176d0d JH |
239 | /* |
240 | * FIXME: This should be done in the irq_request_resources callback | |
dc665b52 BG |
241 | * when the irq is requested, but a few drivers currently fail to do |
242 | * so. | |
52176d0d | 243 | * |
dc665b52 BG |
244 | * Remove this redundant call (along with the corresponding unlock) |
245 | * when those drivers have been fixed. | |
52176d0d | 246 | */ |
d83cee3d | 247 | ret = gpiochip_lock_as_irq(guard.gc, gpio_chip_hwgpio(desc)); |
0eb4c6c2 | 248 | if (ret < 0) |
c38c3a34 | 249 | goto err_clr_bits; |
0eb4c6c2 | 250 | |
2ec74a95 | 251 | ret = request_any_context_irq(data->irq, gpio_sysfs_irq, irq_flags, |
a08f5c21 | 252 | "gpiolib", data); |
52176d0d JH |
253 | if (ret < 0) |
254 | goto err_unlock; | |
0eb4c6c2 | 255 | |
cef1717b | 256 | data->irq_flags = flags; |
2ec74a95 | 257 | |
0eb4c6c2 AC |
258 | return 0; |
259 | ||
52176d0d | 260 | err_unlock: |
d83cee3d | 261 | gpiochip_unlock_as_irq(guard.gc, gpio_chip_hwgpio(desc)); |
c38c3a34 | 262 | err_clr_bits: |
7b925098 BG |
263 | clear_bit(FLAG_EDGE_RISING, &desc->flags); |
264 | clear_bit(FLAG_EDGE_FALLING, &desc->flags); | |
2ec74a95 | 265 | |
0eb4c6c2 AC |
266 | return ret; |
267 | } | |
268 | ||
6ffcb797 JH |
269 | /* |
270 | * Caller holds gpiod-data mutex (unless called after class-device | |
271 | * deregistration). | |
272 | */ | |
7c49c129 | 273 | static void gpio_sysfs_free_irq(struct gpiod_data *data) |
2ec74a95 | 274 | { |
2ec74a95 JH |
275 | struct gpio_desc *desc = data->desc; |
276 | ||
d83cee3d BG |
277 | CLASS(gpio_chip_guard, guard)(desc); |
278 | if (!guard.gc) | |
279 | return; | |
280 | ||
cef1717b | 281 | data->irq_flags = 0; |
2ec74a95 | 282 | free_irq(data->irq, data); |
d83cee3d | 283 | gpiochip_unlock_as_irq(guard.gc, gpio_chip_hwgpio(desc)); |
7b925098 BG |
284 | clear_bit(FLAG_EDGE_RISING, &desc->flags); |
285 | clear_bit(FLAG_EDGE_FALLING, &desc->flags); | |
2ec74a95 JH |
286 | } |
287 | ||
dc665b52 | 288 | static const char *const trigger_names[] = { |
667630ed AS |
289 | [GPIO_IRQF_TRIGGER_NONE] = "none", |
290 | [GPIO_IRQF_TRIGGER_FALLING] = "falling", | |
291 | [GPIO_IRQF_TRIGGER_RISING] = "rising", | |
292 | [GPIO_IRQF_TRIGGER_BOTH] = "both", | |
0eb4c6c2 AC |
293 | }; |
294 | ||
dc665b52 BG |
295 | static ssize_t edge_show(struct device *dev, struct device_attribute *attr, |
296 | char *buf) | |
0eb4c6c2 | 297 | { |
f7d4fb62 BG |
298 | struct gpiod_data *data = container_of(attr, struct gpiod_data, |
299 | edge_attr); | |
667630ed | 300 | int flags; |
0eb4c6c2 | 301 | |
d99c980c BG |
302 | scoped_guard(mutex, &data->mutex) |
303 | flags = data->irq_flags; | |
6ffcb797 | 304 | |
667630ed | 305 | if (flags >= ARRAY_SIZE(trigger_names)) |
e28747da AS |
306 | return 0; |
307 | ||
667630ed | 308 | return sysfs_emit(buf, "%s\n", trigger_names[flags]); |
0eb4c6c2 AC |
309 | } |
310 | ||
dc665b52 BG |
311 | static ssize_t edge_store(struct device *dev, struct device_attribute *attr, |
312 | const char *buf, size_t size) | |
0eb4c6c2 | 313 | { |
f7d4fb62 BG |
314 | struct gpiod_data *data = container_of(attr, struct gpiod_data, |
315 | edge_attr); | |
513246a3 | 316 | ssize_t status = size; |
667630ed | 317 | int flags; |
e4339ce3 | 318 | |
667630ed AS |
319 | flags = sysfs_match_string(trigger_names, buf); |
320 | if (flags < 0) | |
321 | return flags; | |
b91e1807 | 322 | |
d99c980c | 323 | guard(mutex)(&data->mutex); |
0eb4c6c2 | 324 | |
d99c980c BG |
325 | if (flags == data->irq_flags) |
326 | return size; | |
b91e1807 | 327 | |
cef1717b | 328 | if (data->irq_flags) |
7c49c129 | 329 | gpio_sysfs_free_irq(data); |
2ec74a95 | 330 | |
d99c980c BG |
331 | if (!flags) |
332 | return size; | |
0eb4c6c2 | 333 | |
7c49c129 | 334 | status = gpio_sysfs_request_irq(data, flags); |
d99c980c BG |
335 | if (status) |
336 | return status; | |
0eb4c6c2 | 337 | |
7b925098 BG |
338 | gpiod_line_state_notify(data->desc, GPIO_V2_LINE_CHANGED_CONFIG); |
339 | ||
d99c980c | 340 | return size; |
0eb4c6c2 | 341 | } |
0eb4c6c2 | 342 | |
6ffcb797 | 343 | /* Caller holds gpiod-data mutex. */ |
7c49c129 | 344 | static int gpio_sysfs_set_active_low(struct gpiod_data *data, int value) |
0eb4c6c2 | 345 | { |
513246a3 BG |
346 | unsigned int flags = data->irq_flags; |
347 | struct gpio_desc *desc = data->desc; | |
348 | int status = 0; | |
349 | ||
0eb4c6c2 AC |
350 | if (!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) == !!value) |
351 | return 0; | |
352 | ||
fd80b8ba | 353 | assign_bit(FLAG_ACTIVE_LOW, &desc->flags, value); |
0eb4c6c2 AC |
354 | |
355 | /* reconfigure poll(2) support if enabled on one edge only */ | |
cef1717b | 356 | if (flags == GPIO_IRQF_TRIGGER_FALLING || |
dc665b52 | 357 | flags == GPIO_IRQF_TRIGGER_RISING) { |
7c49c129 BG |
358 | gpio_sysfs_free_irq(data); |
359 | status = gpio_sysfs_request_irq(data, flags); | |
0eb4c6c2 AC |
360 | } |
361 | ||
5a7119e0 BG |
362 | gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_CONFIG); |
363 | ||
0eb4c6c2 AC |
364 | return status; |
365 | } | |
366 | ||
6beac9d1 | 367 | static ssize_t active_low_show(struct device *dev, |
dc665b52 | 368 | struct device_attribute *attr, char *buf) |
0eb4c6c2 | 369 | { |
f7d4fb62 BG |
370 | struct gpiod_data *data = container_of(attr, struct gpiod_data, |
371 | active_low_attr); | |
c43960fb | 372 | struct gpio_desc *desc = data->desc; |
e28747da | 373 | int value; |
0eb4c6c2 | 374 | |
d99c980c BG |
375 | scoped_guard(mutex, &data->mutex) |
376 | value = !!test_bit(FLAG_ACTIVE_LOW, &desc->flags); | |
0eb4c6c2 | 377 | |
e28747da | 378 | return sysfs_emit(buf, "%d\n", value); |
0eb4c6c2 AC |
379 | } |
380 | ||
6beac9d1 | 381 | static ssize_t active_low_store(struct device *dev, |
dc665b52 BG |
382 | struct device_attribute *attr, |
383 | const char *buf, size_t size) | |
0eb4c6c2 | 384 | { |
f7d4fb62 BG |
385 | struct gpiod_data *data = container_of(attr, struct gpiod_data, |
386 | active_low_attr); | |
513246a3 BG |
387 | ssize_t status; |
388 | long value; | |
0eb4c6c2 | 389 | |
6b3c1791 AS |
390 | status = kstrtol(buf, 0, &value); |
391 | if (status) | |
392 | return status; | |
393 | ||
d99c980c | 394 | guard(mutex)(&data->mutex); |
0eb4c6c2 | 395 | |
7c49c129 | 396 | return gpio_sysfs_set_active_low(data, value) ?: size; |
0eb4c6c2 | 397 | } |
e69c6db4 | 398 | #endif /* CONFIG_GPIO_SYSFS_LEGACY */ |
0eb4c6c2 | 399 | |
ebbeba12 JH |
400 | static umode_t gpio_is_visible(struct kobject *kobj, struct attribute *attr, |
401 | int n) | |
402 | { | |
f7d4fb62 BG |
403 | struct device_attribute *dev_attr = container_of(attr, |
404 | struct device_attribute, attr); | |
ebbeba12 | 405 | umode_t mode = attr->mode; |
f7d4fb62 BG |
406 | struct gpiod_data *data; |
407 | ||
408 | if (strcmp(attr->name, "direction") == 0) { | |
409 | data = container_of(dev_attr, struct gpiod_data, dir_attr); | |
ebbeba12 | 410 | |
f7d4fb62 | 411 | if (!data->direction_can_change) |
ebbeba12 | 412 | mode = 0; |
e69c6db4 | 413 | #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) |
f7d4fb62 BG |
414 | } else if (strcmp(attr->name, "edge") == 0) { |
415 | data = container_of(dev_attr, struct gpiod_data, edge_attr); | |
416 | ||
417 | if (gpiod_to_irq(data->desc) < 0) | |
ebbeba12 | 418 | mode = 0; |
f7d4fb62 BG |
419 | |
420 | if (!data->direction_can_change && | |
421 | test_bit(FLAG_IS_OUT, &data->desc->flags)) | |
ebbeba12 | 422 | mode = 0; |
e69c6db4 | 423 | #endif /* CONFIG_GPIO_SYSFS_LEGACY */ |
ebbeba12 JH |
424 | } |
425 | ||
426 | return mode; | |
427 | } | |
428 | ||
0eb4c6c2 AC |
429 | /* |
430 | * /sys/class/gpio/gpiochipN/ | |
431 | * /base ... matching gpio_chip.base (N) | |
432 | * /label ... matching gpio_chip.label | |
433 | * /ngpio ... matching gpio_chip.ngpio | |
2028f854 BG |
434 | * |
435 | * AND | |
436 | * | |
437 | * /sys/class/gpio/chipX/ | |
438 | * /export ... export GPIO at given offset | |
439 | * /unexport ... unexport GPIO at given offset | |
440 | * /label ... matching gpio_chip.label | |
441 | * /ngpio ... matching gpio_chip.ngpio | |
0eb4c6c2 AC |
442 | */ |
443 | ||
e69c6db4 | 444 | #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) |
dc665b52 BG |
445 | static ssize_t base_show(struct device *dev, struct device_attribute *attr, |
446 | char *buf) | |
0eb4c6c2 | 447 | { |
fd197928 | 448 | const struct gpiodev_data *data = dev_get_drvdata(dev); |
0eb4c6c2 | 449 | |
fd197928 | 450 | return sysfs_emit(buf, "%u\n", data->gdev->base); |
0eb4c6c2 | 451 | } |
6beac9d1 | 452 | static DEVICE_ATTR_RO(base); |
e69c6db4 | 453 | #endif /* CONFIG_GPIO_SYSFS_LEGACY */ |
0eb4c6c2 | 454 | |
dc665b52 BG |
455 | static ssize_t label_show(struct device *dev, struct device_attribute *attr, |
456 | char *buf) | |
0eb4c6c2 | 457 | { |
fd197928 | 458 | const struct gpiodev_data *data = dev_get_drvdata(dev); |
0eb4c6c2 | 459 | |
fd197928 | 460 | return sysfs_emit(buf, "%s\n", data->gdev->label); |
0eb4c6c2 | 461 | } |
6beac9d1 | 462 | static DEVICE_ATTR_RO(label); |
0eb4c6c2 | 463 | |
dc665b52 BG |
464 | static ssize_t ngpio_show(struct device *dev, struct device_attribute *attr, |
465 | char *buf) | |
0eb4c6c2 | 466 | { |
fd197928 | 467 | const struct gpiodev_data *data = dev_get_drvdata(dev); |
0eb4c6c2 | 468 | |
fd197928 | 469 | return sysfs_emit(buf, "%u\n", data->gdev->ngpio); |
0eb4c6c2 | 470 | } |
6beac9d1 | 471 | static DEVICE_ATTR_RO(ngpio); |
0eb4c6c2 | 472 | |
2028f854 BG |
473 | static int export_gpio_desc(struct gpio_desc *desc) |
474 | { | |
475 | int offset, ret; | |
476 | ||
477 | CLASS(gpio_chip_guard, guard)(desc); | |
478 | if (!guard.gc) | |
479 | return -ENODEV; | |
480 | ||
481 | offset = gpio_chip_hwgpio(desc); | |
482 | if (!gpiochip_line_is_valid(guard.gc, offset)) { | |
483 | pr_debug_ratelimited("%s: GPIO %d masked\n", __func__, | |
484 | gpio_chip_hwgpio(desc)); | |
485 | return -EINVAL; | |
486 | } | |
487 | ||
488 | /* | |
489 | * No extra locking here; FLAG_SYSFS just signifies that the | |
490 | * request and export were done by on behalf of userspace, so | |
491 | * they may be undone on its behalf too. | |
492 | */ | |
493 | ||
494 | ret = gpiod_request_user(desc, "sysfs"); | |
495 | if (ret) | |
496 | return ret; | |
497 | ||
498 | ret = gpiod_set_transitory(desc, false); | |
499 | if (ret) { | |
500 | gpiod_free(desc); | |
501 | return ret; | |
502 | } | |
503 | ||
504 | ret = gpiod_export(desc, true); | |
505 | if (ret < 0) { | |
506 | gpiod_free(desc); | |
507 | } else { | |
508 | set_bit(FLAG_SYSFS, &desc->flags); | |
509 | gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_REQUESTED); | |
510 | } | |
511 | ||
512 | return ret; | |
513 | } | |
514 | ||
515 | static int unexport_gpio_desc(struct gpio_desc *desc) | |
516 | { | |
517 | /* | |
518 | * No extra locking here; FLAG_SYSFS just signifies that the | |
519 | * request and export were done by on behalf of userspace, so | |
520 | * they may be undone on its behalf too. | |
521 | */ | |
522 | if (!test_and_clear_bit(FLAG_SYSFS, &desc->flags)) | |
523 | return -EINVAL; | |
524 | ||
525 | gpiod_unexport(desc); | |
526 | gpiod_free(desc); | |
527 | ||
528 | return 0; | |
529 | } | |
530 | ||
531 | static ssize_t do_chip_export_store(struct device *dev, | |
532 | struct device_attribute *attr, | |
533 | const char *buf, ssize_t size, | |
534 | int (*handler)(struct gpio_desc *desc)) | |
535 | { | |
536 | struct gpiodev_data *data = dev_get_drvdata(dev); | |
537 | struct gpio_device *gdev = data->gdev; | |
538 | struct gpio_desc *desc; | |
539 | unsigned int gpio; | |
540 | int ret; | |
541 | ||
542 | ret = kstrtouint(buf, 0, &gpio); | |
543 | if (ret) | |
544 | return ret; | |
545 | ||
546 | desc = gpio_device_get_desc(gdev, gpio); | |
547 | if (IS_ERR(desc)) | |
548 | return PTR_ERR(desc); | |
549 | ||
550 | ret = handler(desc); | |
551 | if (ret) | |
552 | return ret; | |
553 | ||
554 | return size; | |
555 | } | |
556 | ||
557 | static ssize_t chip_export_store(struct device *dev, | |
558 | struct device_attribute *attr, | |
559 | const char *buf, size_t size) | |
560 | { | |
561 | return do_chip_export_store(dev, attr, buf, size, export_gpio_desc); | |
562 | } | |
563 | ||
564 | static struct device_attribute dev_attr_export = __ATTR(export, 0200, NULL, | |
565 | chip_export_store); | |
566 | ||
567 | static ssize_t chip_unexport_store(struct device *dev, | |
568 | struct device_attribute *attr, | |
569 | const char *buf, size_t size) | |
570 | { | |
571 | return do_chip_export_store(dev, attr, buf, size, unexport_gpio_desc); | |
572 | } | |
573 | ||
574 | static struct device_attribute dev_attr_unexport = __ATTR(unexport, 0200, | |
575 | NULL, | |
576 | chip_unexport_store); | |
577 | ||
e69c6db4 | 578 | #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) |
121b6a79 | 579 | static struct attribute *gpiochip_attrs[] = { |
0eb4c6c2 AC |
580 | &dev_attr_base.attr, |
581 | &dev_attr_label.attr, | |
582 | &dev_attr_ngpio.attr, | |
583 | NULL, | |
584 | }; | |
121b6a79 | 585 | ATTRIBUTE_GROUPS(gpiochip); |
e69c6db4 | 586 | #endif /* CONFIG_GPIO_SYSFS_LEGACY */ |
0eb4c6c2 | 587 | |
2028f854 BG |
588 | static struct attribute *gpiochip_ext_attrs[] = { |
589 | &dev_attr_label.attr, | |
590 | &dev_attr_ngpio.attr, | |
591 | &dev_attr_export.attr, | |
592 | &dev_attr_unexport.attr, | |
593 | NULL | |
594 | }; | |
595 | ATTRIBUTE_GROUPS(gpiochip_ext); | |
596 | ||
e69c6db4 | 597 | #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) |
0eb4c6c2 AC |
598 | /* |
599 | * /sys/class/gpio/export ... write-only | |
600 | * integer N ... number of GPIO to export (full access) | |
601 | * /sys/class/gpio/unexport ... write-only | |
602 | * integer N ... number of GPIO to unexport | |
603 | */ | |
75a2d422 | 604 | static ssize_t export_store(const struct class *class, |
dc665b52 BG |
605 | const struct class_attribute *attr, |
606 | const char *buf, size_t len) | |
0eb4c6c2 | 607 | { |
513246a3 | 608 | struct gpio_desc *desc; |
2028f854 | 609 | int status; |
513246a3 | 610 | long gpio; |
0eb4c6c2 AC |
611 | |
612 | status = kstrtol(buf, 0, &gpio); | |
d83cee3d BG |
613 | if (status) |
614 | return status; | |
0eb4c6c2 | 615 | |
f13a0b0b | 616 | desc = gpio_to_desc(gpio); |
0eb4c6c2 AC |
617 | /* reject invalid GPIOs */ |
618 | if (!desc) { | |
37d5a6d6 | 619 | pr_debug_ratelimited("%s: invalid GPIO %ld\n", __func__, gpio); |
0eb4c6c2 AC |
620 | return -EINVAL; |
621 | } | |
d83cee3d | 622 | |
2028f854 | 623 | status = export_gpio_desc(desc); |
0eb4c6c2 AC |
624 | if (status) |
625 | pr_debug("%s: status %d\n", __func__, status); | |
626 | return status ? : len; | |
627 | } | |
d83bb159 | 628 | static CLASS_ATTR_WO(export); |
0eb4c6c2 | 629 | |
75a2d422 | 630 | static ssize_t unexport_store(const struct class *class, |
dc665b52 BG |
631 | const struct class_attribute *attr, |
632 | const char *buf, size_t len) | |
0eb4c6c2 | 633 | { |
513246a3 BG |
634 | struct gpio_desc *desc; |
635 | int status; | |
636 | long gpio; | |
0eb4c6c2 AC |
637 | |
638 | status = kstrtol(buf, 0, &gpio); | |
639 | if (status < 0) | |
2028f854 | 640 | return status; |
0eb4c6c2 | 641 | |
f13a0b0b | 642 | desc = gpio_to_desc(gpio); |
d74e3166 | 643 | /* reject bogus commands (gpiod_unexport() ignores them) */ |
0eb4c6c2 | 644 | if (!desc) { |
37d5a6d6 | 645 | pr_debug_ratelimited("%s: invalid GPIO %ld\n", __func__, gpio); |
0eb4c6c2 AC |
646 | return -EINVAL; |
647 | } | |
648 | ||
2028f854 | 649 | status = unexport_gpio_desc(desc); |
0eb4c6c2 AC |
650 | if (status) |
651 | pr_debug("%s: status %d\n", __func__, status); | |
652 | return status ? : len; | |
653 | } | |
d83bb159 | 654 | static CLASS_ATTR_WO(unexport); |
0eb4c6c2 | 655 | |
d83bb159 GKH |
656 | static struct attribute *gpio_class_attrs[] = { |
657 | &class_attr_export.attr, | |
658 | &class_attr_unexport.attr, | |
659 | NULL, | |
0eb4c6c2 | 660 | }; |
d83bb159 | 661 | ATTRIBUTE_GROUPS(gpio_class); |
e69c6db4 | 662 | #endif /* CONFIG_GPIO_SYSFS_LEGACY */ |
0eb4c6c2 | 663 | |
b6f7aeaf | 664 | static const struct class gpio_class = { |
0eb4c6c2 | 665 | .name = "gpio", |
e69c6db4 | 666 | #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) |
b6f7aeaf | 667 | .class_groups = gpio_class_groups, |
e69c6db4 | 668 | #endif /* CONFIG_GPIO_SYSFS_LEGACY */ |
0eb4c6c2 AC |
669 | }; |
670 | ||
fd197928 BG |
671 | static int match_gdev(struct device *dev, const void *desc) |
672 | { | |
673 | struct gpiodev_data *data = dev_get_drvdata(dev); | |
674 | const struct gpio_device *gdev = desc; | |
675 | ||
676 | return data && data->gdev == gdev; | |
677 | } | |
678 | ||
679 | static struct gpiodev_data * | |
680 | gdev_get_data(struct gpio_device *gdev) __must_hold(&sysfs_lock) | |
681 | { | |
2028f854 BG |
682 | /* |
683 | * Find the first device in GPIO class that matches. Whether that's | |
684 | * the one indexed by GPIO base or device ID doesn't matter, it has | |
685 | * the same address set as driver data. | |
686 | */ | |
fd197928 BG |
687 | struct device *cdev __free(put_device) = class_find_device(&gpio_class, |
688 | NULL, gdev, | |
689 | match_gdev); | |
690 | if (!cdev) | |
691 | return NULL; | |
692 | ||
693 | return dev_get_drvdata(cdev); | |
694 | }; | |
695 | ||
f7d4fb62 BG |
696 | static void gpiod_attr_init(struct device_attribute *dev_attr, const char *name, |
697 | ssize_t (*show)(struct device *dev, | |
698 | struct device_attribute *attr, | |
699 | char *buf), | |
700 | ssize_t (*store)(struct device *dev, | |
701 | struct device_attribute *attr, | |
702 | const char *buf, size_t count)) | |
703 | { | |
704 | sysfs_attr_init(&dev_attr->attr); | |
705 | dev_attr->attr.name = name; | |
706 | dev_attr->attr.mode = 0644; | |
707 | dev_attr->show = show; | |
708 | dev_attr->store = store; | |
709 | } | |
710 | ||
0eb4c6c2 AC |
711 | /** |
712 | * gpiod_export - export a GPIO through sysfs | |
2d9d0519 TR |
713 | * @desc: GPIO to make available, already requested |
714 | * @direction_may_change: true if userspace may change GPIO direction | |
0eb4c6c2 AC |
715 | * Context: arch_initcall or later |
716 | * | |
717 | * When drivers want to make a GPIO accessible to userspace after they | |
718 | * have requested it -- perhaps while debugging, or as part of their | |
719 | * public interface -- they may use this routine. If the GPIO can | |
720 | * change direction (some can't) and the caller allows it, userspace | |
721 | * will see "direction" sysfs attribute which may be used to change | |
722 | * the gpio's direction. A "value" attribute will always be provided. | |
723 | * | |
94bd9ce1 AS |
724 | * Returns: |
725 | * 0 on success, or negative errno on failure. | |
0eb4c6c2 AC |
726 | */ |
727 | int gpiod_export(struct gpio_desc *desc, bool direction_may_change) | |
728 | { | |
4fa93223 | 729 | char *path __free(kfree) = NULL; |
1cd53df7 | 730 | struct gpiodev_data *gdev_data; |
12faec7e | 731 | struct gpiod_data *desc_data; |
513246a3 | 732 | struct gpio_device *gdev; |
f7d4fb62 | 733 | struct attribute **attrs; |
700cdf7e | 734 | int status; |
0eb4c6c2 AC |
735 | |
736 | /* can't export until sysfs is available ... */ | |
6f14c022 | 737 | if (!class_is_registered(&gpio_class)) { |
0eb4c6c2 AC |
738 | pr_debug("%s: called too early!\n", __func__); |
739 | return -ENOENT; | |
740 | } | |
741 | ||
742 | if (!desc) { | |
743 | pr_debug("%s: invalid gpio descriptor\n", __func__); | |
744 | return -EINVAL; | |
745 | } | |
746 | ||
d83cee3d BG |
747 | CLASS(gpio_chip_guard, guard)(desc); |
748 | if (!guard.gc) | |
749 | return -ENODEV; | |
750 | ||
8636f19c | 751 | if (test_and_set_bit(FLAG_EXPORT, &desc->flags)) |
35b54533 BG |
752 | return -EPERM; |
753 | ||
fdeb8e15 | 754 | gdev = desc->gdev; |
483d8211 | 755 | |
f4af1671 | 756 | guard(mutex)(&sysfs_lock); |
0eb4c6c2 | 757 | |
35b54533 BG |
758 | if (!test_bit(FLAG_REQUESTED, &desc->flags)) { |
759 | gpiod_dbg(desc, "%s: unavailable (not requested)\n", __func__); | |
0eb4c6c2 | 760 | status = -EPERM; |
f4af1671 | 761 | goto err_clear_bit; |
0eb4c6c2 | 762 | } |
0eb4c6c2 | 763 | |
12faec7e BG |
764 | desc_data = kzalloc(sizeof(*desc_data), GFP_KERNEL); |
765 | if (!desc_data) { | |
c43960fb | 766 | status = -ENOMEM; |
f4af1671 | 767 | goto err_clear_bit; |
c43960fb JH |
768 | } |
769 | ||
12faec7e BG |
770 | desc_data->desc = desc; |
771 | mutex_init(&desc_data->mutex); | |
d83cee3d | 772 | if (guard.gc->direction_input && guard.gc->direction_output) |
12faec7e | 773 | desc_data->direction_can_change = direction_may_change; |
427fdeef | 774 | else |
12faec7e | 775 | desc_data->direction_can_change = false; |
c43960fb | 776 | |
f7d4fb62 BG |
777 | gpiod_attr_init(&desc_data->dir_attr, "direction", |
778 | direction_show, direction_store); | |
779 | gpiod_attr_init(&desc_data->val_attr, "value", value_show, value_store); | |
e69c6db4 BG |
780 | |
781 | #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) | |
f7d4fb62 BG |
782 | gpiod_attr_init(&desc_data->edge_attr, "edge", edge_show, edge_store); |
783 | gpiod_attr_init(&desc_data->active_low_attr, "active_low", | |
784 | active_low_show, active_low_store); | |
785 | ||
786 | attrs = desc_data->class_attrs; | |
787 | desc_data->class_attr_group.is_visible = gpio_is_visible; | |
788 | attrs[GPIO_SYSFS_LINE_CLASS_ATTR_DIRECTION] = &desc_data->dir_attr.attr; | |
789 | attrs[GPIO_SYSFS_LINE_CLASS_ATTR_VALUE] = &desc_data->val_attr.attr; | |
790 | attrs[GPIO_SYSFS_LINE_CLASS_ATTR_EDGE] = &desc_data->edge_attr.attr; | |
791 | attrs[GPIO_SYSFS_LINE_CLASS_ATTR_ACTIVE_LOW] = &desc_data->active_low_attr.attr; | |
792 | ||
793 | desc_data->class_attr_group.attrs = desc_data->class_attrs; | |
794 | desc_data->class_attr_groups[0] = &desc_data->class_attr_group; | |
795 | ||
1cd53df7 BG |
796 | /* |
797 | * Note: we need to continue passing desc_data here as there's still | |
798 | * at least one known user of gpiod_export_link() in the tree. This | |
799 | * function still uses class_find_device() internally. | |
800 | */ | |
801 | desc_data->dev = device_create_with_groups(&gpio_class, &gdev->dev, | |
802 | MKDEV(0, 0), desc_data, | |
803 | desc_data->class_attr_groups, | |
804 | "gpio%u", | |
805 | desc_to_gpio(desc)); | |
806 | if (IS_ERR(desc_data->dev)) { | |
807 | status = PTR_ERR(desc_data->dev); | |
c43960fb | 808 | goto err_free_data; |
0eb4c6c2 AC |
809 | } |
810 | ||
1cd53df7 BG |
811 | desc_data->value_kn = sysfs_get_dirent(desc_data->dev->kobj.sd, |
812 | "value"); | |
12faec7e | 813 | if (!desc_data->value_kn) { |
c38c3a34 BG |
814 | status = -ENODEV; |
815 | goto err_unregister_device; | |
816 | } | |
e69c6db4 | 817 | #endif /* CONFIG_GPIO_SYSFS_LEGACY */ |
c38c3a34 | 818 | |
1cd53df7 BG |
819 | gdev_data = gdev_get_data(gdev); |
820 | if (!gdev_data) { | |
821 | status = -ENODEV; | |
4fa93223 BG |
822 | goto err_put_dirent; |
823 | } | |
824 | ||
825 | desc_data->chip_attr_group.name = kasprintf(GFP_KERNEL, "gpio%u", | |
826 | gpio_chip_hwgpio(desc)); | |
827 | if (!desc_data->chip_attr_group.name) { | |
828 | status = -ENOMEM; | |
829 | goto err_put_dirent; | |
830 | } | |
831 | ||
832 | attrs = desc_data->chip_attrs; | |
833 | desc_data->chip_attr_group.is_visible = gpio_is_visible; | |
834 | attrs[GPIO_SYSFS_LINE_CHIP_ATTR_DIRECTION] = &desc_data->dir_attr.attr; | |
835 | attrs[GPIO_SYSFS_LINE_CHIP_ATTR_VALUE] = &desc_data->val_attr.attr; | |
836 | ||
837 | desc_data->chip_attr_group.attrs = attrs; | |
838 | desc_data->chip_attr_groups[0] = &desc_data->chip_attr_group; | |
839 | ||
840 | desc_data->parent = &gdev_data->cdev_id->kobj; | |
841 | status = sysfs_create_groups(desc_data->parent, | |
842 | desc_data->chip_attr_groups); | |
843 | if (status) | |
844 | goto err_free_name; | |
845 | ||
846 | path = kasprintf(GFP_KERNEL, "gpio%u/value", gpio_chip_hwgpio(desc)); | |
847 | if (!path) { | |
848 | status = -ENOMEM; | |
849 | goto err_remove_groups; | |
1cd53df7 BG |
850 | } |
851 | ||
852 | list_add(&desc_data->list, &gdev_data->exported_lines); | |
853 | ||
0eb4c6c2 AC |
854 | return 0; |
855 | ||
4fa93223 BG |
856 | err_remove_groups: |
857 | sysfs_remove_groups(desc_data->parent, desc_data->chip_attr_groups); | |
858 | err_free_name: | |
859 | kfree(desc_data->chip_attr_group.name); | |
860 | err_put_dirent: | |
e69c6db4 | 861 | #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) |
4fa93223 | 862 | sysfs_put(desc_data->value_kn); |
c38c3a34 | 863 | err_unregister_device: |
1cd53df7 | 864 | device_unregister(desc_data->dev); |
c43960fb | 865 | err_free_data: |
e69c6db4 | 866 | #endif /* CONFIG_GPIO_SYSFS_LEGACY */ |
12faec7e | 867 | kfree(desc_data); |
f4af1671 | 868 | err_clear_bit: |
35b54533 | 869 | clear_bit(FLAG_EXPORT, &desc->flags); |
0eb4c6c2 AC |
870 | gpiod_dbg(desc, "%s: status %d\n", __func__, status); |
871 | return status; | |
872 | } | |
873 | EXPORT_SYMBOL_GPL(gpiod_export); | |
874 | ||
e69c6db4 | 875 | #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) |
c43960fb | 876 | static int match_export(struct device *dev, const void *desc) |
0eb4c6c2 | 877 | { |
c43960fb JH |
878 | struct gpiod_data *data = dev_get_drvdata(dev); |
879 | ||
32ad0b9a | 880 | return gpiod_is_equal(data->desc, desc); |
0eb4c6c2 | 881 | } |
e69c6db4 | 882 | #endif /* CONFIG_GPIO_SYSFS_LEGACY */ |
0eb4c6c2 AC |
883 | |
884 | /** | |
885 | * gpiod_export_link - create a sysfs link to an exported GPIO node | |
886 | * @dev: device under which to create symlink | |
887 | * @name: name of the symlink | |
2d9d0519 | 888 | * @desc: GPIO to create symlink to, already exported |
0eb4c6c2 AC |
889 | * |
890 | * Set up a symlink from /sys/.../dev/name to /sys/class/gpio/gpioN | |
891 | * node. Caller is responsible for unlinking. | |
892 | * | |
94bd9ce1 AS |
893 | * Returns: |
894 | * 0 on success, or negative errno on failure. | |
0eb4c6c2 AC |
895 | */ |
896 | int gpiod_export_link(struct device *dev, const char *name, | |
897 | struct gpio_desc *desc) | |
898 | { | |
e69c6db4 | 899 | #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) |
56d30ec1 JH |
900 | struct device *cdev; |
901 | int ret; | |
0eb4c6c2 AC |
902 | |
903 | if (!desc) { | |
904 | pr_warn("%s: invalid GPIO\n", __func__); | |
905 | return -EINVAL; | |
906 | } | |
907 | ||
56d30ec1 JH |
908 | cdev = class_find_device(&gpio_class, NULL, desc, match_export); |
909 | if (!cdev) | |
910 | return -ENODEV; | |
0eb4c6c2 | 911 | |
56d30ec1 JH |
912 | ret = sysfs_create_link(&dev->kobj, &cdev->kobj, name); |
913 | put_device(cdev); | |
0eb4c6c2 | 914 | |
56d30ec1 | 915 | return ret; |
e69c6db4 BG |
916 | #else |
917 | return -EOPNOTSUPP; | |
918 | #endif /* CONFIG_GPIO_SYSFS_LEGACY */ | |
0eb4c6c2 AC |
919 | } |
920 | EXPORT_SYMBOL_GPL(gpiod_export_link); | |
921 | ||
0eb4c6c2 | 922 | /** |
31963eb0 | 923 | * gpiod_unexport - reverse effect of gpiod_export() |
2d9d0519 | 924 | * @desc: GPIO to make unavailable |
0eb4c6c2 | 925 | * |
31963eb0 | 926 | * This is implicit on gpiod_free(). |
0eb4c6c2 AC |
927 | */ |
928 | void gpiod_unexport(struct gpio_desc *desc) | |
929 | { | |
5607f5ed | 930 | struct gpiod_data *tmp, *desc_data = NULL; |
1cd53df7 BG |
931 | struct gpiodev_data *gdev_data; |
932 | struct gpio_device *gdev; | |
0eb4c6c2 AC |
933 | |
934 | if (!desc) { | |
935 | pr_warn("%s: invalid GPIO\n", __func__); | |
936 | return; | |
937 | } | |
938 | ||
f4af1671 BG |
939 | scoped_guard(mutex, &sysfs_lock) { |
940 | if (!test_bit(FLAG_EXPORT, &desc->flags)) | |
941 | return; | |
72eba6f6 | 942 | |
1cd53df7 BG |
943 | gdev = gpiod_to_gpio_device(desc); |
944 | gdev_data = gdev_get_data(gdev); | |
945 | if (!gdev_data) | |
946 | return; | |
947 | ||
5607f5ed DC |
948 | list_for_each_entry(tmp, &gdev_data->exported_lines, list) { |
949 | if (gpiod_is_equal(desc, tmp->desc)) { | |
950 | desc_data = tmp; | |
1cd53df7 | 951 | break; |
5607f5ed DC |
952 | } |
953 | } | |
1cd53df7 BG |
954 | |
955 | if (!desc_data) | |
f4af1671 | 956 | return; |
72eba6f6 | 957 | |
1cd53df7 | 958 | list_del(&desc_data->list); |
f4af1671 | 959 | clear_bit(FLAG_EXPORT, &desc->flags); |
e69c6db4 | 960 | #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) |
12faec7e | 961 | sysfs_put(desc_data->value_kn); |
1cd53df7 | 962 | device_unregister(desc_data->dev); |
0eb4c6c2 | 963 | |
f4af1671 BG |
964 | /* |
965 | * Release irq after deregistration to prevent race with | |
966 | * edge_store. | |
967 | */ | |
12faec7e BG |
968 | if (desc_data->irq_flags) |
969 | gpio_sysfs_free_irq(desc_data); | |
e69c6db4 | 970 | #endif /* CONFIG_GPIO_SYSFS_LEGACY */ |
4fa93223 BG |
971 | |
972 | sysfs_remove_groups(desc_data->parent, | |
973 | desc_data->chip_attr_groups); | |
f4af1671 | 974 | } |
0eb4c6c2 | 975 | |
12faec7e BG |
976 | mutex_destroy(&desc_data->mutex); |
977 | kfree(desc_data); | |
0eb4c6c2 AC |
978 | } |
979 | EXPORT_SYMBOL_GPL(gpiod_unexport); | |
980 | ||
afbc4f31 | 981 | int gpiochip_sysfs_register(struct gpio_device *gdev) |
0eb4c6c2 | 982 | { |
fd197928 | 983 | struct gpiodev_data *data; |
d83cee3d | 984 | struct gpio_chip *chip; |
513246a3 | 985 | struct device *parent; |
e6bb7857 | 986 | int err; |
0eb4c6c2 | 987 | |
426577bd JH |
988 | /* |
989 | * Many systems add gpio chips for SOC support very early, | |
0eb4c6c2 | 990 | * before driver model support is available. In those cases we |
426577bd | 991 | * register later, in gpiolib_sysfs_init() ... here we just |
0eb4c6c2 AC |
992 | * verify that _some_ field of gpio_class got initialized. |
993 | */ | |
6f14c022 | 994 | if (!class_is_registered(&gpio_class)) |
0eb4c6c2 AC |
995 | return 0; |
996 | ||
d83cee3d BG |
997 | guard(srcu)(&gdev->srcu); |
998 | ||
d82b9e08 | 999 | chip = srcu_dereference(gdev->chip, &gdev->srcu); |
d83cee3d BG |
1000 | if (!chip) |
1001 | return -ENODEV; | |
1002 | ||
d27c1728 BJZ |
1003 | /* |
1004 | * For sysfs backward compatibility we need to preserve this | |
1005 | * preferred parenting to the gpio_chip parent field, if set. | |
1006 | */ | |
1007 | if (chip->parent) | |
1008 | parent = chip->parent; | |
1009 | else | |
1010 | parent = &gdev->dev; | |
1011 | ||
fd197928 BG |
1012 | data = kmalloc(sizeof(*data), GFP_KERNEL); |
1013 | if (!data) | |
1014 | return -ENOMEM; | |
1015 | ||
1016 | data->gdev = gdev; | |
1cd53df7 | 1017 | INIT_LIST_HEAD(&data->exported_lines); |
3ff74be5 | 1018 | |
f4af1671 | 1019 | guard(mutex)(&sysfs_lock); |
fd197928 | 1020 | |
e69c6db4 | 1021 | #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) |
fd197928 BG |
1022 | /* use chip->base for the ID; it's already known to be unique */ |
1023 | data->cdev_base = device_create_with_groups(&gpio_class, parent, | |
1024 | MKDEV(0, 0), data, | |
1025 | gpiochip_groups, | |
1026 | GPIOCHIP_NAME "%d", | |
1027 | chip->base); | |
1028 | if (IS_ERR(data->cdev_base)) { | |
e6bb7857 | 1029 | err = PTR_ERR(data->cdev_base); |
fd197928 | 1030 | kfree(data); |
e6bb7857 | 1031 | return err; |
fd197928 | 1032 | } |
e69c6db4 | 1033 | #endif /* CONFIG_GPIO_SYSFS_LEGACY */ |
0eb4c6c2 | 1034 | |
2028f854 BG |
1035 | data->cdev_id = device_create_with_groups(&gpio_class, parent, |
1036 | MKDEV(0, 0), data, | |
1037 | gpiochip_ext_groups, | |
1038 | "chip%d", gdev->id); | |
1039 | if (IS_ERR(data->cdev_id)) { | |
e69c6db4 | 1040 | #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) |
2028f854 | 1041 | device_unregister(data->cdev_base); |
e69c6db4 | 1042 | #endif /* CONFIG_GPIO_SYSFS_LEGACY */ |
2028f854 BG |
1043 | err = PTR_ERR(data->cdev_id); |
1044 | kfree(data); | |
1045 | return err; | |
1046 | } | |
1047 | ||
6a4b6b0a | 1048 | return 0; |
0eb4c6c2 AC |
1049 | } |
1050 | ||
afbc4f31 | 1051 | void gpiochip_sysfs_unregister(struct gpio_device *gdev) |
0eb4c6c2 | 1052 | { |
fd197928 | 1053 | struct gpiodev_data *data; |
483d8211 | 1054 | struct gpio_desc *desc; |
d83cee3d | 1055 | struct gpio_chip *chip; |
0eb4c6c2 | 1056 | |
59cba4a0 | 1057 | scoped_guard(mutex, &sysfs_lock) { |
fd197928 BG |
1058 | data = gdev_get_data(gdev); |
1059 | if (!data) | |
59cba4a0 | 1060 | return; |
0eb4c6c2 | 1061 | |
e69c6db4 | 1062 | #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) |
fd197928 | 1063 | device_unregister(data->cdev_base); |
e69c6db4 | 1064 | #endif /* CONFIG_GPIO_SYSFS_LEGACY */ |
2028f854 | 1065 | device_unregister(data->cdev_id); |
fd197928 | 1066 | kfree(data); |
59cba4a0 | 1067 | } |
483d8211 | 1068 | |
d83cee3d BG |
1069 | guard(srcu)(&gdev->srcu); |
1070 | ||
d82b9e08 | 1071 | chip = srcu_dereference(gdev->chip, &gdev->srcu); |
be91c19e | 1072 | if (!chip) |
d83cee3d BG |
1073 | return; |
1074 | ||
483d8211 | 1075 | /* unregister gpiod class devices owned by sysfs */ |
20d9b3b5 AS |
1076 | for_each_gpio_desc_with_flag(chip, desc, FLAG_SYSFS) { |
1077 | gpiod_unexport(desc); | |
80c78fbe | 1078 | gpiod_free(desc); |
20d9b3b5 | 1079 | } |
0eb4c6c2 AC |
1080 | } |
1081 | ||
2a9101e8 BG |
1082 | /* |
1083 | * We're not really looking for a device - we just want to iterate over the | |
1084 | * list and call this callback for each GPIO device. This is why this function | |
1085 | * always returns 0. | |
1086 | */ | |
1087 | static int gpiofind_sysfs_register(struct gpio_chip *gc, const void *data) | |
1088 | { | |
1089 | struct gpio_device *gdev = gc->gpiodev; | |
1090 | int ret; | |
1091 | ||
2a9101e8 BG |
1092 | ret = gpiochip_sysfs_register(gdev); |
1093 | if (ret) | |
1094 | chip_err(gc, "failed to register the sysfs entry: %d\n", ret); | |
1095 | ||
1096 | return 0; | |
1097 | } | |
1098 | ||
0eb4c6c2 AC |
1099 | static int __init gpiolib_sysfs_init(void) |
1100 | { | |
2a9101e8 | 1101 | int status; |
0eb4c6c2 AC |
1102 | |
1103 | status = class_register(&gpio_class); | |
1104 | if (status < 0) | |
1105 | return status; | |
1106 | ||
1107 | /* Scan and register the gpio_chips which registered very | |
1108 | * early (e.g. before the class_register above was called). | |
1109 | * | |
1110 | * We run before arch_initcall() so chip->dev nodes can have | |
d74e3166 | 1111 | * registered, and so arch_initcall() can always gpiod_export(). |
0eb4c6c2 | 1112 | */ |
2a9101e8 | 1113 | (void)gpio_device_find(NULL, gpiofind_sysfs_register); |
efb8235b | 1114 | |
2a9101e8 | 1115 | return 0; |
0eb4c6c2 AC |
1116 | } |
1117 | postcore_initcall(gpiolib_sysfs_init); |