xref: /openbmc/linux/drivers/gpio/gpiolib-cdev.c (revision 883f919818437122462754174e21c38991a18934)
1925ca369SKent Gibson // SPDX-License-Identifier: GPL-2.0
2925ca369SKent Gibson 
3d189f627SKent Gibson #include <linux/anon_inodes.h>
4925ca369SKent Gibson #include <linux/bitmap.h>
5d189f627SKent Gibson #include <linux/cdev.h>
6d189f627SKent Gibson #include <linux/compat.h>
7925ca369SKent Gibson #include <linux/device.h>
8925ca369SKent Gibson #include <linux/err.h>
9d189f627SKent Gibson #include <linux/file.h>
10925ca369SKent Gibson #include <linux/gpio.h>
11925ca369SKent Gibson #include <linux/gpio/driver.h>
12d189f627SKent Gibson #include <linux/interrupt.h>
13d189f627SKent Gibson #include <linux/irqreturn.h>
14d189f627SKent Gibson #include <linux/kernel.h>
15925ca369SKent Gibson #include <linux/kfifo.h>
16d189f627SKent Gibson #include <linux/module.h>
17d189f627SKent Gibson #include <linux/pinctrl/consumer.h>
18925ca369SKent Gibson #include <linux/poll.h>
19d189f627SKent Gibson #include <linux/spinlock.h>
20925ca369SKent Gibson #include <linux/timekeeping.h>
21d189f627SKent Gibson #include <linux/uaccess.h>
22925ca369SKent Gibson #include <uapi/linux/gpio.h>
23925ca369SKent Gibson 
24925ca369SKent Gibson #include "gpiolib.h"
25925ca369SKent Gibson #include "gpiolib-cdev.h"
26925ca369SKent Gibson 
27925ca369SKent Gibson /* Character device interface to GPIO.
28925ca369SKent Gibson  *
29925ca369SKent Gibson  * The GPIO character device, /dev/gpiochipN, provides userspace an
30925ca369SKent Gibson  * interface to gpiolib GPIOs via ioctl()s.
31925ca369SKent Gibson  */
32925ca369SKent Gibson 
33925ca369SKent Gibson /*
34925ca369SKent Gibson  * GPIO line handle management
35925ca369SKent Gibson  */
36925ca369SKent Gibson 
37925ca369SKent Gibson /**
38925ca369SKent Gibson  * struct linehandle_state - contains the state of a userspace handle
39925ca369SKent Gibson  * @gdev: the GPIO device the handle pertains to
40925ca369SKent Gibson  * @label: consumer label used to tag descriptors
41925ca369SKent Gibson  * @descs: the GPIO descriptors held by this handle
4252b7b596SKent Gibson  * @num_descs: the number of descriptors held in the descs array
43925ca369SKent Gibson  */
44925ca369SKent Gibson struct linehandle_state {
45925ca369SKent Gibson 	struct gpio_device *gdev;
46925ca369SKent Gibson 	const char *label;
47925ca369SKent Gibson 	struct gpio_desc *descs[GPIOHANDLES_MAX];
4852b7b596SKent Gibson 	u32 num_descs;
49925ca369SKent Gibson };
50925ca369SKent Gibson 
51925ca369SKent Gibson #define GPIOHANDLE_REQUEST_VALID_FLAGS \
52925ca369SKent Gibson 	(GPIOHANDLE_REQUEST_INPUT | \
53925ca369SKent Gibson 	GPIOHANDLE_REQUEST_OUTPUT | \
54925ca369SKent Gibson 	GPIOHANDLE_REQUEST_ACTIVE_LOW | \
55925ca369SKent Gibson 	GPIOHANDLE_REQUEST_BIAS_PULL_UP | \
56925ca369SKent Gibson 	GPIOHANDLE_REQUEST_BIAS_PULL_DOWN | \
57925ca369SKent Gibson 	GPIOHANDLE_REQUEST_BIAS_DISABLE | \
58925ca369SKent Gibson 	GPIOHANDLE_REQUEST_OPEN_DRAIN | \
59925ca369SKent Gibson 	GPIOHANDLE_REQUEST_OPEN_SOURCE)
60925ca369SKent Gibson 
61925ca369SKent Gibson static int linehandle_validate_flags(u32 flags)
62925ca369SKent Gibson {
63925ca369SKent Gibson 	/* Return an error if an unknown flag is set */
64925ca369SKent Gibson 	if (flags & ~GPIOHANDLE_REQUEST_VALID_FLAGS)
65925ca369SKent Gibson 		return -EINVAL;
66925ca369SKent Gibson 
67925ca369SKent Gibson 	/*
68925ca369SKent Gibson 	 * Do not allow both INPUT & OUTPUT flags to be set as they are
69925ca369SKent Gibson 	 * contradictory.
70925ca369SKent Gibson 	 */
71925ca369SKent Gibson 	if ((flags & GPIOHANDLE_REQUEST_INPUT) &&
72925ca369SKent Gibson 	    (flags & GPIOHANDLE_REQUEST_OUTPUT))
73925ca369SKent Gibson 		return -EINVAL;
74925ca369SKent Gibson 
75925ca369SKent Gibson 	/*
76925ca369SKent Gibson 	 * Do not allow OPEN_SOURCE & OPEN_DRAIN flags in a single request. If
77925ca369SKent Gibson 	 * the hardware actually supports enabling both at the same time the
78925ca369SKent Gibson 	 * electrical result would be disastrous.
79925ca369SKent Gibson 	 */
80925ca369SKent Gibson 	if ((flags & GPIOHANDLE_REQUEST_OPEN_DRAIN) &&
81925ca369SKent Gibson 	    (flags & GPIOHANDLE_REQUEST_OPEN_SOURCE))
82925ca369SKent Gibson 		return -EINVAL;
83925ca369SKent Gibson 
84925ca369SKent Gibson 	/* OPEN_DRAIN and OPEN_SOURCE flags only make sense for output mode. */
85925ca369SKent Gibson 	if (!(flags & GPIOHANDLE_REQUEST_OUTPUT) &&
86925ca369SKent Gibson 	    ((flags & GPIOHANDLE_REQUEST_OPEN_DRAIN) ||
87925ca369SKent Gibson 	     (flags & GPIOHANDLE_REQUEST_OPEN_SOURCE)))
88925ca369SKent Gibson 		return -EINVAL;
89925ca369SKent Gibson 
90925ca369SKent Gibson 	/* Bias flags only allowed for input or output mode. */
91925ca369SKent Gibson 	if (!((flags & GPIOHANDLE_REQUEST_INPUT) ||
92925ca369SKent Gibson 	      (flags & GPIOHANDLE_REQUEST_OUTPUT)) &&
93925ca369SKent Gibson 	    ((flags & GPIOHANDLE_REQUEST_BIAS_DISABLE) ||
94925ca369SKent Gibson 	     (flags & GPIOHANDLE_REQUEST_BIAS_PULL_UP) ||
95925ca369SKent Gibson 	     (flags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN)))
96925ca369SKent Gibson 		return -EINVAL;
97925ca369SKent Gibson 
98925ca369SKent Gibson 	/* Only one bias flag can be set. */
99925ca369SKent Gibson 	if (((flags & GPIOHANDLE_REQUEST_BIAS_DISABLE) &&
100925ca369SKent Gibson 	     (flags & (GPIOHANDLE_REQUEST_BIAS_PULL_DOWN |
101925ca369SKent Gibson 		       GPIOHANDLE_REQUEST_BIAS_PULL_UP))) ||
102925ca369SKent Gibson 	    ((flags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN) &&
103925ca369SKent Gibson 	     (flags & GPIOHANDLE_REQUEST_BIAS_PULL_UP)))
104925ca369SKent Gibson 		return -EINVAL;
105925ca369SKent Gibson 
106925ca369SKent Gibson 	return 0;
107925ca369SKent Gibson }
108925ca369SKent Gibson 
109c274b58aSKent Gibson static void linehandle_flags_to_desc_flags(u32 lflags, unsigned long *flagsp)
110c274b58aSKent Gibson {
111c274b58aSKent Gibson 	assign_bit(FLAG_ACTIVE_LOW, flagsp,
112c274b58aSKent Gibson 		   lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW);
113c274b58aSKent Gibson 	assign_bit(FLAG_OPEN_DRAIN, flagsp,
114c274b58aSKent Gibson 		   lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN);
115c274b58aSKent Gibson 	assign_bit(FLAG_OPEN_SOURCE, flagsp,
116c274b58aSKent Gibson 		   lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE);
117c274b58aSKent Gibson 	assign_bit(FLAG_PULL_UP, flagsp,
118c274b58aSKent Gibson 		   lflags & GPIOHANDLE_REQUEST_BIAS_PULL_UP);
119c274b58aSKent Gibson 	assign_bit(FLAG_PULL_DOWN, flagsp,
120c274b58aSKent Gibson 		   lflags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN);
121c274b58aSKent Gibson 	assign_bit(FLAG_BIAS_DISABLE, flagsp,
122c274b58aSKent Gibson 		   lflags & GPIOHANDLE_REQUEST_BIAS_DISABLE);
123c274b58aSKent Gibson }
124c274b58aSKent Gibson 
125925ca369SKent Gibson static long linehandle_set_config(struct linehandle_state *lh,
126925ca369SKent Gibson 				  void __user *ip)
127925ca369SKent Gibson {
128925ca369SKent Gibson 	struct gpiohandle_config gcnf;
129925ca369SKent Gibson 	struct gpio_desc *desc;
130925ca369SKent Gibson 	int i, ret;
131925ca369SKent Gibson 	u32 lflags;
132925ca369SKent Gibson 
133925ca369SKent Gibson 	if (copy_from_user(&gcnf, ip, sizeof(gcnf)))
134925ca369SKent Gibson 		return -EFAULT;
135925ca369SKent Gibson 
136925ca369SKent Gibson 	lflags = gcnf.flags;
137925ca369SKent Gibson 	ret = linehandle_validate_flags(lflags);
138925ca369SKent Gibson 	if (ret)
139925ca369SKent Gibson 		return ret;
140925ca369SKent Gibson 
14152b7b596SKent Gibson 	for (i = 0; i < lh->num_descs; i++) {
142925ca369SKent Gibson 		desc = lh->descs[i];
143c274b58aSKent Gibson 		linehandle_flags_to_desc_flags(gcnf.flags, &desc->flags);
144925ca369SKent Gibson 
145925ca369SKent Gibson 		/*
146925ca369SKent Gibson 		 * Lines have to be requested explicitly for input
147925ca369SKent Gibson 		 * or output, else the line will be treated "as is".
148925ca369SKent Gibson 		 */
149925ca369SKent Gibson 		if (lflags & GPIOHANDLE_REQUEST_OUTPUT) {
150925ca369SKent Gibson 			int val = !!gcnf.default_values[i];
151925ca369SKent Gibson 
152925ca369SKent Gibson 			ret = gpiod_direction_output(desc, val);
153925ca369SKent Gibson 			if (ret)
154925ca369SKent Gibson 				return ret;
155925ca369SKent Gibson 		} else if (lflags & GPIOHANDLE_REQUEST_INPUT) {
156925ca369SKent Gibson 			ret = gpiod_direction_input(desc);
157925ca369SKent Gibson 			if (ret)
158925ca369SKent Gibson 				return ret;
159925ca369SKent Gibson 		}
160925ca369SKent Gibson 
1616accc376SKent Gibson 		blocking_notifier_call_chain(&desc->gdev->notifier,
162925ca369SKent Gibson 					     GPIOLINE_CHANGED_CONFIG, desc);
163925ca369SKent Gibson 	}
164925ca369SKent Gibson 	return 0;
165925ca369SKent Gibson }
166925ca369SKent Gibson 
16749bc5279SKent Gibson static long linehandle_ioctl(struct file *file, unsigned int cmd,
168925ca369SKent Gibson 			     unsigned long arg)
169925ca369SKent Gibson {
17049bc5279SKent Gibson 	struct linehandle_state *lh = file->private_data;
171925ca369SKent Gibson 	void __user *ip = (void __user *)arg;
172925ca369SKent Gibson 	struct gpiohandle_data ghd;
173925ca369SKent Gibson 	DECLARE_BITMAP(vals, GPIOHANDLES_MAX);
174925ca369SKent Gibson 	int i;
175925ca369SKent Gibson 
176925ca369SKent Gibson 	if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) {
177925ca369SKent Gibson 		/* NOTE: It's ok to read values of output lines. */
178925ca369SKent Gibson 		int ret = gpiod_get_array_value_complex(false,
179925ca369SKent Gibson 							true,
18052b7b596SKent Gibson 							lh->num_descs,
181925ca369SKent Gibson 							lh->descs,
182925ca369SKent Gibson 							NULL,
183925ca369SKent Gibson 							vals);
184925ca369SKent Gibson 		if (ret)
185925ca369SKent Gibson 			return ret;
186925ca369SKent Gibson 
187925ca369SKent Gibson 		memset(&ghd, 0, sizeof(ghd));
18852b7b596SKent Gibson 		for (i = 0; i < lh->num_descs; i++)
189925ca369SKent Gibson 			ghd.values[i] = test_bit(i, vals);
190925ca369SKent Gibson 
191925ca369SKent Gibson 		if (copy_to_user(ip, &ghd, sizeof(ghd)))
192925ca369SKent Gibson 			return -EFAULT;
193925ca369SKent Gibson 
194925ca369SKent Gibson 		return 0;
195925ca369SKent Gibson 	} else if (cmd == GPIOHANDLE_SET_LINE_VALUES_IOCTL) {
196925ca369SKent Gibson 		/*
197925ca369SKent Gibson 		 * All line descriptors were created at once with the same
198925ca369SKent Gibson 		 * flags so just check if the first one is really output.
199925ca369SKent Gibson 		 */
200925ca369SKent Gibson 		if (!test_bit(FLAG_IS_OUT, &lh->descs[0]->flags))
201925ca369SKent Gibson 			return -EPERM;
202925ca369SKent Gibson 
203925ca369SKent Gibson 		if (copy_from_user(&ghd, ip, sizeof(ghd)))
204925ca369SKent Gibson 			return -EFAULT;
205925ca369SKent Gibson 
206925ca369SKent Gibson 		/* Clamp all values to [0,1] */
20752b7b596SKent Gibson 		for (i = 0; i < lh->num_descs; i++)
208925ca369SKent Gibson 			__assign_bit(i, vals, ghd.values[i]);
209925ca369SKent Gibson 
210925ca369SKent Gibson 		/* Reuse the array setting function */
211925ca369SKent Gibson 		return gpiod_set_array_value_complex(false,
212925ca369SKent Gibson 						     true,
21352b7b596SKent Gibson 						     lh->num_descs,
214925ca369SKent Gibson 						     lh->descs,
215925ca369SKent Gibson 						     NULL,
216925ca369SKent Gibson 						     vals);
217925ca369SKent Gibson 	} else if (cmd == GPIOHANDLE_SET_CONFIG_IOCTL) {
218925ca369SKent Gibson 		return linehandle_set_config(lh, ip);
219925ca369SKent Gibson 	}
220925ca369SKent Gibson 	return -EINVAL;
221925ca369SKent Gibson }
222925ca369SKent Gibson 
223925ca369SKent Gibson #ifdef CONFIG_COMPAT
22449bc5279SKent Gibson static long linehandle_ioctl_compat(struct file *file, unsigned int cmd,
225925ca369SKent Gibson 				    unsigned long arg)
226925ca369SKent Gibson {
22749bc5279SKent Gibson 	return linehandle_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
228925ca369SKent Gibson }
229925ca369SKent Gibson #endif
230925ca369SKent Gibson 
231*883f9198SKent Gibson static void linehandle_free(struct linehandle_state *lh)
232925ca369SKent Gibson {
233925ca369SKent Gibson 	int i;
234925ca369SKent Gibson 
23552b7b596SKent Gibson 	for (i = 0; i < lh->num_descs; i++)
236*883f9198SKent Gibson 		if (lh->descs[i])
237925ca369SKent Gibson 			gpiod_free(lh->descs[i]);
238925ca369SKent Gibson 	kfree(lh->label);
239*883f9198SKent Gibson 	put_device(&lh->gdev->dev);
240925ca369SKent Gibson 	kfree(lh);
241*883f9198SKent Gibson }
242*883f9198SKent Gibson 
243*883f9198SKent Gibson static int linehandle_release(struct inode *inode, struct file *file)
244*883f9198SKent Gibson {
245*883f9198SKent Gibson 	linehandle_free(file->private_data);
246925ca369SKent Gibson 	return 0;
247925ca369SKent Gibson }
248925ca369SKent Gibson 
249925ca369SKent Gibson static const struct file_operations linehandle_fileops = {
250925ca369SKent Gibson 	.release = linehandle_release,
251925ca369SKent Gibson 	.owner = THIS_MODULE,
252925ca369SKent Gibson 	.llseek = noop_llseek,
253925ca369SKent Gibson 	.unlocked_ioctl = linehandle_ioctl,
254925ca369SKent Gibson #ifdef CONFIG_COMPAT
255925ca369SKent Gibson 	.compat_ioctl = linehandle_ioctl_compat,
256925ca369SKent Gibson #endif
257925ca369SKent Gibson };
258925ca369SKent Gibson 
259925ca369SKent Gibson static int linehandle_create(struct gpio_device *gdev, void __user *ip)
260925ca369SKent Gibson {
261925ca369SKent Gibson 	struct gpiohandle_request handlereq;
262925ca369SKent Gibson 	struct linehandle_state *lh;
263925ca369SKent Gibson 	struct file *file;
264*883f9198SKent Gibson 	int fd, i, ret;
265925ca369SKent Gibson 	u32 lflags;
266925ca369SKent Gibson 
267925ca369SKent Gibson 	if (copy_from_user(&handlereq, ip, sizeof(handlereq)))
268925ca369SKent Gibson 		return -EFAULT;
269925ca369SKent Gibson 	if ((handlereq.lines == 0) || (handlereq.lines > GPIOHANDLES_MAX))
270925ca369SKent Gibson 		return -EINVAL;
271925ca369SKent Gibson 
272925ca369SKent Gibson 	lflags = handlereq.flags;
273925ca369SKent Gibson 
274925ca369SKent Gibson 	ret = linehandle_validate_flags(lflags);
275925ca369SKent Gibson 	if (ret)
276925ca369SKent Gibson 		return ret;
277925ca369SKent Gibson 
278925ca369SKent Gibson 	lh = kzalloc(sizeof(*lh), GFP_KERNEL);
279925ca369SKent Gibson 	if (!lh)
280925ca369SKent Gibson 		return -ENOMEM;
281925ca369SKent Gibson 	lh->gdev = gdev;
282925ca369SKent Gibson 	get_device(&gdev->dev);
283925ca369SKent Gibson 
284925ca369SKent Gibson 	/* Make sure this is terminated */
285925ca369SKent Gibson 	handlereq.consumer_label[sizeof(handlereq.consumer_label)-1] = '\0';
286925ca369SKent Gibson 	if (strlen(handlereq.consumer_label)) {
287925ca369SKent Gibson 		lh->label = kstrdup(handlereq.consumer_label,
288925ca369SKent Gibson 				    GFP_KERNEL);
289925ca369SKent Gibson 		if (!lh->label) {
290925ca369SKent Gibson 			ret = -ENOMEM;
291925ca369SKent Gibson 			goto out_free_lh;
292925ca369SKent Gibson 		}
293925ca369SKent Gibson 	}
294925ca369SKent Gibson 
295*883f9198SKent Gibson 	lh->num_descs = handlereq.lines;
296*883f9198SKent Gibson 
297925ca369SKent Gibson 	/* Request each GPIO */
298925ca369SKent Gibson 	for (i = 0; i < handlereq.lines; i++) {
299925ca369SKent Gibson 		u32 offset = handlereq.lineoffsets[i];
300925ca369SKent Gibson 		struct gpio_desc *desc = gpiochip_get_desc(gdev->chip, offset);
301925ca369SKent Gibson 
302925ca369SKent Gibson 		if (IS_ERR(desc)) {
303925ca369SKent Gibson 			ret = PTR_ERR(desc);
304*883f9198SKent Gibson 			goto out_free_lh;
305925ca369SKent Gibson 		}
306925ca369SKent Gibson 
307925ca369SKent Gibson 		ret = gpiod_request(desc, lh->label);
308925ca369SKent Gibson 		if (ret)
309*883f9198SKent Gibson 			goto out_free_lh;
310925ca369SKent Gibson 		lh->descs[i] = desc;
311c274b58aSKent Gibson 		linehandle_flags_to_desc_flags(handlereq.flags, &desc->flags);
312925ca369SKent Gibson 
313925ca369SKent Gibson 		ret = gpiod_set_transitory(desc, false);
314925ca369SKent Gibson 		if (ret < 0)
315*883f9198SKent Gibson 			goto out_free_lh;
316925ca369SKent Gibson 
317925ca369SKent Gibson 		/*
318925ca369SKent Gibson 		 * Lines have to be requested explicitly for input
319925ca369SKent Gibson 		 * or output, else the line will be treated "as is".
320925ca369SKent Gibson 		 */
321925ca369SKent Gibson 		if (lflags & GPIOHANDLE_REQUEST_OUTPUT) {
322925ca369SKent Gibson 			int val = !!handlereq.default_values[i];
323925ca369SKent Gibson 
324925ca369SKent Gibson 			ret = gpiod_direction_output(desc, val);
325925ca369SKent Gibson 			if (ret)
326*883f9198SKent Gibson 				goto out_free_lh;
327925ca369SKent Gibson 		} else if (lflags & GPIOHANDLE_REQUEST_INPUT) {
328925ca369SKent Gibson 			ret = gpiod_direction_input(desc);
329925ca369SKent Gibson 			if (ret)
330*883f9198SKent Gibson 				goto out_free_lh;
331925ca369SKent Gibson 		}
332925ca369SKent Gibson 
3336accc376SKent Gibson 		blocking_notifier_call_chain(&desc->gdev->notifier,
334925ca369SKent Gibson 					     GPIOLINE_CHANGED_REQUESTED, desc);
335925ca369SKent Gibson 
336925ca369SKent Gibson 		dev_dbg(&gdev->dev, "registered chardev handle for line %d\n",
337925ca369SKent Gibson 			offset);
338925ca369SKent Gibson 	}
339925ca369SKent Gibson 
340925ca369SKent Gibson 	fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
341925ca369SKent Gibson 	if (fd < 0) {
342925ca369SKent Gibson 		ret = fd;
343*883f9198SKent Gibson 		goto out_free_lh;
344925ca369SKent Gibson 	}
345925ca369SKent Gibson 
346925ca369SKent Gibson 	file = anon_inode_getfile("gpio-linehandle",
347925ca369SKent Gibson 				  &linehandle_fileops,
348925ca369SKent Gibson 				  lh,
349925ca369SKent Gibson 				  O_RDONLY | O_CLOEXEC);
350925ca369SKent Gibson 	if (IS_ERR(file)) {
351925ca369SKent Gibson 		ret = PTR_ERR(file);
352925ca369SKent Gibson 		goto out_put_unused_fd;
353925ca369SKent Gibson 	}
354925ca369SKent Gibson 
355925ca369SKent Gibson 	handlereq.fd = fd;
356925ca369SKent Gibson 	if (copy_to_user(ip, &handlereq, sizeof(handlereq))) {
357925ca369SKent Gibson 		/*
358925ca369SKent Gibson 		 * fput() will trigger the release() callback, so do not go onto
359925ca369SKent Gibson 		 * the regular error cleanup path here.
360925ca369SKent Gibson 		 */
361925ca369SKent Gibson 		fput(file);
362925ca369SKent Gibson 		put_unused_fd(fd);
363925ca369SKent Gibson 		return -EFAULT;
364925ca369SKent Gibson 	}
365925ca369SKent Gibson 
366925ca369SKent Gibson 	fd_install(fd, file);
367925ca369SKent Gibson 
368925ca369SKent Gibson 	dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n",
36952b7b596SKent Gibson 		lh->num_descs);
370925ca369SKent Gibson 
371925ca369SKent Gibson 	return 0;
372925ca369SKent Gibson 
373925ca369SKent Gibson out_put_unused_fd:
374925ca369SKent Gibson 	put_unused_fd(fd);
375925ca369SKent Gibson out_free_lh:
376*883f9198SKent Gibson 	linehandle_free(lh);
377925ca369SKent Gibson 	return ret;
378925ca369SKent Gibson }
379925ca369SKent Gibson 
380925ca369SKent Gibson /*
381925ca369SKent Gibson  * GPIO line event management
382925ca369SKent Gibson  */
383925ca369SKent Gibson 
384925ca369SKent Gibson /**
385925ca369SKent Gibson  * struct lineevent_state - contains the state of a userspace event
386925ca369SKent Gibson  * @gdev: the GPIO device the event pertains to
387925ca369SKent Gibson  * @label: consumer label used to tag descriptors
388925ca369SKent Gibson  * @desc: the GPIO descriptor held by this event
389925ca369SKent Gibson  * @eflags: the event flags this line was requested with
390925ca369SKent Gibson  * @irq: the interrupt that trigger in response to events on this GPIO
391925ca369SKent Gibson  * @wait: wait queue that handles blocking reads of events
392925ca369SKent Gibson  * @events: KFIFO for the GPIO events
393925ca369SKent Gibson  * @timestamp: cache for the timestamp storing it between hardirq
394925ca369SKent Gibson  * and IRQ thread, used to bring the timestamp close to the actual
395925ca369SKent Gibson  * event
396925ca369SKent Gibson  */
397925ca369SKent Gibson struct lineevent_state {
398925ca369SKent Gibson 	struct gpio_device *gdev;
399925ca369SKent Gibson 	const char *label;
400925ca369SKent Gibson 	struct gpio_desc *desc;
401925ca369SKent Gibson 	u32 eflags;
402925ca369SKent Gibson 	int irq;
403925ca369SKent Gibson 	wait_queue_head_t wait;
404925ca369SKent Gibson 	DECLARE_KFIFO(events, struct gpioevent_data, 16);
405925ca369SKent Gibson 	u64 timestamp;
406925ca369SKent Gibson };
407925ca369SKent Gibson 
408925ca369SKent Gibson #define GPIOEVENT_REQUEST_VALID_FLAGS \
409925ca369SKent Gibson 	(GPIOEVENT_REQUEST_RISING_EDGE | \
410925ca369SKent Gibson 	GPIOEVENT_REQUEST_FALLING_EDGE)
411925ca369SKent Gibson 
41249bc5279SKent Gibson static __poll_t lineevent_poll(struct file *file,
413925ca369SKent Gibson 			       struct poll_table_struct *wait)
414925ca369SKent Gibson {
41549bc5279SKent Gibson 	struct lineevent_state *le = file->private_data;
416925ca369SKent Gibson 	__poll_t events = 0;
417925ca369SKent Gibson 
41849bc5279SKent Gibson 	poll_wait(file, &le->wait, wait);
419925ca369SKent Gibson 
420925ca369SKent Gibson 	if (!kfifo_is_empty_spinlocked_noirqsave(&le->events, &le->wait.lock))
421925ca369SKent Gibson 		events = EPOLLIN | EPOLLRDNORM;
422925ca369SKent Gibson 
423925ca369SKent Gibson 	return events;
424925ca369SKent Gibson }
425925ca369SKent Gibson 
426925ca369SKent Gibson 
42749bc5279SKent Gibson static ssize_t lineevent_read(struct file *file,
428925ca369SKent Gibson 			      char __user *buf,
429925ca369SKent Gibson 			      size_t count,
430925ca369SKent Gibson 			      loff_t *f_ps)
431925ca369SKent Gibson {
43249bc5279SKent Gibson 	struct lineevent_state *le = file->private_data;
433925ca369SKent Gibson 	struct gpioevent_data ge;
434925ca369SKent Gibson 	ssize_t bytes_read = 0;
435925ca369SKent Gibson 	int ret;
436925ca369SKent Gibson 
437925ca369SKent Gibson 	if (count < sizeof(ge))
438925ca369SKent Gibson 		return -EINVAL;
439925ca369SKent Gibson 
440925ca369SKent Gibson 	do {
441925ca369SKent Gibson 		spin_lock(&le->wait.lock);
442925ca369SKent Gibson 		if (kfifo_is_empty(&le->events)) {
443925ca369SKent Gibson 			if (bytes_read) {
444925ca369SKent Gibson 				spin_unlock(&le->wait.lock);
445925ca369SKent Gibson 				return bytes_read;
446925ca369SKent Gibson 			}
447925ca369SKent Gibson 
44849bc5279SKent Gibson 			if (file->f_flags & O_NONBLOCK) {
449925ca369SKent Gibson 				spin_unlock(&le->wait.lock);
450925ca369SKent Gibson 				return -EAGAIN;
451925ca369SKent Gibson 			}
452925ca369SKent Gibson 
453925ca369SKent Gibson 			ret = wait_event_interruptible_locked(le->wait,
454925ca369SKent Gibson 					!kfifo_is_empty(&le->events));
455925ca369SKent Gibson 			if (ret) {
456925ca369SKent Gibson 				spin_unlock(&le->wait.lock);
457925ca369SKent Gibson 				return ret;
458925ca369SKent Gibson 			}
459925ca369SKent Gibson 		}
460925ca369SKent Gibson 
461925ca369SKent Gibson 		ret = kfifo_out(&le->events, &ge, 1);
462925ca369SKent Gibson 		spin_unlock(&le->wait.lock);
463925ca369SKent Gibson 		if (ret != 1) {
464925ca369SKent Gibson 			/*
465925ca369SKent Gibson 			 * This should never happen - we were holding the lock
466925ca369SKent Gibson 			 * from the moment we learned the fifo is no longer
467925ca369SKent Gibson 			 * empty until now.
468925ca369SKent Gibson 			 */
469925ca369SKent Gibson 			ret = -EIO;
470925ca369SKent Gibson 			break;
471925ca369SKent Gibson 		}
472925ca369SKent Gibson 
473925ca369SKent Gibson 		if (copy_to_user(buf + bytes_read, &ge, sizeof(ge)))
474925ca369SKent Gibson 			return -EFAULT;
475925ca369SKent Gibson 		bytes_read += sizeof(ge);
476925ca369SKent Gibson 	} while (count >= bytes_read + sizeof(ge));
477925ca369SKent Gibson 
478925ca369SKent Gibson 	return bytes_read;
479925ca369SKent Gibson }
480925ca369SKent Gibson 
48149bc5279SKent Gibson static int lineevent_release(struct inode *inode, struct file *file)
482925ca369SKent Gibson {
48349bc5279SKent Gibson 	struct lineevent_state *le = file->private_data;
484925ca369SKent Gibson 	struct gpio_device *gdev = le->gdev;
485925ca369SKent Gibson 
486925ca369SKent Gibson 	free_irq(le->irq, le);
487925ca369SKent Gibson 	gpiod_free(le->desc);
488925ca369SKent Gibson 	kfree(le->label);
489925ca369SKent Gibson 	kfree(le);
490925ca369SKent Gibson 	put_device(&gdev->dev);
491925ca369SKent Gibson 	return 0;
492925ca369SKent Gibson }
493925ca369SKent Gibson 
49449bc5279SKent Gibson static long lineevent_ioctl(struct file *file, unsigned int cmd,
495925ca369SKent Gibson 			    unsigned long arg)
496925ca369SKent Gibson {
49749bc5279SKent Gibson 	struct lineevent_state *le = file->private_data;
498925ca369SKent Gibson 	void __user *ip = (void __user *)arg;
499925ca369SKent Gibson 	struct gpiohandle_data ghd;
500925ca369SKent Gibson 
501925ca369SKent Gibson 	/*
502925ca369SKent Gibson 	 * We can get the value for an event line but not set it,
503925ca369SKent Gibson 	 * because it is input by definition.
504925ca369SKent Gibson 	 */
505925ca369SKent Gibson 	if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) {
506925ca369SKent Gibson 		int val;
507925ca369SKent Gibson 
508925ca369SKent Gibson 		memset(&ghd, 0, sizeof(ghd));
509925ca369SKent Gibson 
510925ca369SKent Gibson 		val = gpiod_get_value_cansleep(le->desc);
511925ca369SKent Gibson 		if (val < 0)
512925ca369SKent Gibson 			return val;
513925ca369SKent Gibson 		ghd.values[0] = val;
514925ca369SKent Gibson 
515925ca369SKent Gibson 		if (copy_to_user(ip, &ghd, sizeof(ghd)))
516925ca369SKent Gibson 			return -EFAULT;
517925ca369SKent Gibson 
518925ca369SKent Gibson 		return 0;
519925ca369SKent Gibson 	}
520925ca369SKent Gibson 	return -EINVAL;
521925ca369SKent Gibson }
522925ca369SKent Gibson 
523925ca369SKent Gibson #ifdef CONFIG_COMPAT
52449bc5279SKent Gibson static long lineevent_ioctl_compat(struct file *file, unsigned int cmd,
525925ca369SKent Gibson 				   unsigned long arg)
526925ca369SKent Gibson {
52749bc5279SKent Gibson 	return lineevent_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
528925ca369SKent Gibson }
529925ca369SKent Gibson #endif
530925ca369SKent Gibson 
531925ca369SKent Gibson static const struct file_operations lineevent_fileops = {
532925ca369SKent Gibson 	.release = lineevent_release,
533925ca369SKent Gibson 	.read = lineevent_read,
534925ca369SKent Gibson 	.poll = lineevent_poll,
535925ca369SKent Gibson 	.owner = THIS_MODULE,
536925ca369SKent Gibson 	.llseek = noop_llseek,
537925ca369SKent Gibson 	.unlocked_ioctl = lineevent_ioctl,
538925ca369SKent Gibson #ifdef CONFIG_COMPAT
539925ca369SKent Gibson 	.compat_ioctl = lineevent_ioctl_compat,
540925ca369SKent Gibson #endif
541925ca369SKent Gibson };
542925ca369SKent Gibson 
543925ca369SKent Gibson static irqreturn_t lineevent_irq_thread(int irq, void *p)
544925ca369SKent Gibson {
545925ca369SKent Gibson 	struct lineevent_state *le = p;
546925ca369SKent Gibson 	struct gpioevent_data ge;
547925ca369SKent Gibson 	int ret;
548925ca369SKent Gibson 
549925ca369SKent Gibson 	/* Do not leak kernel stack to userspace */
550925ca369SKent Gibson 	memset(&ge, 0, sizeof(ge));
551925ca369SKent Gibson 
552925ca369SKent Gibson 	/*
553925ca369SKent Gibson 	 * We may be running from a nested threaded interrupt in which case
554925ca369SKent Gibson 	 * we didn't get the timestamp from lineevent_irq_handler().
555925ca369SKent Gibson 	 */
556925ca369SKent Gibson 	if (!le->timestamp)
557925ca369SKent Gibson 		ge.timestamp = ktime_get_ns();
558925ca369SKent Gibson 	else
559925ca369SKent Gibson 		ge.timestamp = le->timestamp;
560925ca369SKent Gibson 
561925ca369SKent Gibson 	if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE
562925ca369SKent Gibson 	    && le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
563925ca369SKent Gibson 		int level = gpiod_get_value_cansleep(le->desc);
564925ca369SKent Gibson 
565925ca369SKent Gibson 		if (level)
566925ca369SKent Gibson 			/* Emit low-to-high event */
567925ca369SKent Gibson 			ge.id = GPIOEVENT_EVENT_RISING_EDGE;
568925ca369SKent Gibson 		else
569925ca369SKent Gibson 			/* Emit high-to-low event */
570925ca369SKent Gibson 			ge.id = GPIOEVENT_EVENT_FALLING_EDGE;
571925ca369SKent Gibson 	} else if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE) {
572925ca369SKent Gibson 		/* Emit low-to-high event */
573925ca369SKent Gibson 		ge.id = GPIOEVENT_EVENT_RISING_EDGE;
574925ca369SKent Gibson 	} else if (le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
575925ca369SKent Gibson 		/* Emit high-to-low event */
576925ca369SKent Gibson 		ge.id = GPIOEVENT_EVENT_FALLING_EDGE;
577925ca369SKent Gibson 	} else {
578925ca369SKent Gibson 		return IRQ_NONE;
579925ca369SKent Gibson 	}
580925ca369SKent Gibson 
581925ca369SKent Gibson 	ret = kfifo_in_spinlocked_noirqsave(&le->events, &ge,
582925ca369SKent Gibson 					    1, &le->wait.lock);
583925ca369SKent Gibson 	if (ret)
584925ca369SKent Gibson 		wake_up_poll(&le->wait, EPOLLIN);
585925ca369SKent Gibson 	else
586925ca369SKent Gibson 		pr_debug_ratelimited("event FIFO is full - event dropped\n");
587925ca369SKent Gibson 
588925ca369SKent Gibson 	return IRQ_HANDLED;
589925ca369SKent Gibson }
590925ca369SKent Gibson 
591925ca369SKent Gibson static irqreturn_t lineevent_irq_handler(int irq, void *p)
592925ca369SKent Gibson {
593925ca369SKent Gibson 	struct lineevent_state *le = p;
594925ca369SKent Gibson 
595925ca369SKent Gibson 	/*
596925ca369SKent Gibson 	 * Just store the timestamp in hardirq context so we get it as
597925ca369SKent Gibson 	 * close in time as possible to the actual event.
598925ca369SKent Gibson 	 */
599925ca369SKent Gibson 	le->timestamp = ktime_get_ns();
600925ca369SKent Gibson 
601925ca369SKent Gibson 	return IRQ_WAKE_THREAD;
602925ca369SKent Gibson }
603925ca369SKent Gibson 
604925ca369SKent Gibson static int lineevent_create(struct gpio_device *gdev, void __user *ip)
605925ca369SKent Gibson {
606925ca369SKent Gibson 	struct gpioevent_request eventreq;
607925ca369SKent Gibson 	struct lineevent_state *le;
608925ca369SKent Gibson 	struct gpio_desc *desc;
609925ca369SKent Gibson 	struct file *file;
610925ca369SKent Gibson 	u32 offset;
611925ca369SKent Gibson 	u32 lflags;
612925ca369SKent Gibson 	u32 eflags;
613925ca369SKent Gibson 	int fd;
614925ca369SKent Gibson 	int ret;
615925ca369SKent Gibson 	int irqflags = 0;
616925ca369SKent Gibson 
617925ca369SKent Gibson 	if (copy_from_user(&eventreq, ip, sizeof(eventreq)))
618925ca369SKent Gibson 		return -EFAULT;
619925ca369SKent Gibson 
620925ca369SKent Gibson 	offset = eventreq.lineoffset;
621925ca369SKent Gibson 	lflags = eventreq.handleflags;
622925ca369SKent Gibson 	eflags = eventreq.eventflags;
623925ca369SKent Gibson 
624925ca369SKent Gibson 	desc = gpiochip_get_desc(gdev->chip, offset);
625925ca369SKent Gibson 	if (IS_ERR(desc))
626925ca369SKent Gibson 		return PTR_ERR(desc);
627925ca369SKent Gibson 
628925ca369SKent Gibson 	/* Return an error if a unknown flag is set */
629925ca369SKent Gibson 	if ((lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS) ||
630925ca369SKent Gibson 	    (eflags & ~GPIOEVENT_REQUEST_VALID_FLAGS))
631925ca369SKent Gibson 		return -EINVAL;
632925ca369SKent Gibson 
633925ca369SKent Gibson 	/* This is just wrong: we don't look for events on output lines */
634925ca369SKent Gibson 	if ((lflags & GPIOHANDLE_REQUEST_OUTPUT) ||
635925ca369SKent Gibson 	    (lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN) ||
636925ca369SKent Gibson 	    (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE))
637925ca369SKent Gibson 		return -EINVAL;
638925ca369SKent Gibson 
639925ca369SKent Gibson 	/* Only one bias flag can be set. */
640925ca369SKent Gibson 	if (((lflags & GPIOHANDLE_REQUEST_BIAS_DISABLE) &&
641925ca369SKent Gibson 	     (lflags & (GPIOHANDLE_REQUEST_BIAS_PULL_DOWN |
642925ca369SKent Gibson 			GPIOHANDLE_REQUEST_BIAS_PULL_UP))) ||
643925ca369SKent Gibson 	    ((lflags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN) &&
644925ca369SKent Gibson 	     (lflags & GPIOHANDLE_REQUEST_BIAS_PULL_UP)))
645925ca369SKent Gibson 		return -EINVAL;
646925ca369SKent Gibson 
647925ca369SKent Gibson 	le = kzalloc(sizeof(*le), GFP_KERNEL);
648925ca369SKent Gibson 	if (!le)
649925ca369SKent Gibson 		return -ENOMEM;
650925ca369SKent Gibson 	le->gdev = gdev;
651925ca369SKent Gibson 	get_device(&gdev->dev);
652925ca369SKent Gibson 
653925ca369SKent Gibson 	/* Make sure this is terminated */
654925ca369SKent Gibson 	eventreq.consumer_label[sizeof(eventreq.consumer_label)-1] = '\0';
655925ca369SKent Gibson 	if (strlen(eventreq.consumer_label)) {
656925ca369SKent Gibson 		le->label = kstrdup(eventreq.consumer_label,
657925ca369SKent Gibson 				    GFP_KERNEL);
658925ca369SKent Gibson 		if (!le->label) {
659925ca369SKent Gibson 			ret = -ENOMEM;
660925ca369SKent Gibson 			goto out_free_le;
661925ca369SKent Gibson 		}
662925ca369SKent Gibson 	}
663925ca369SKent Gibson 
664925ca369SKent Gibson 	ret = gpiod_request(desc, le->label);
665925ca369SKent Gibson 	if (ret)
666925ca369SKent Gibson 		goto out_free_label;
667925ca369SKent Gibson 	le->desc = desc;
668925ca369SKent Gibson 	le->eflags = eflags;
669925ca369SKent Gibson 
670c274b58aSKent Gibson 	linehandle_flags_to_desc_flags(lflags, &desc->flags);
671925ca369SKent Gibson 
672925ca369SKent Gibson 	ret = gpiod_direction_input(desc);
673925ca369SKent Gibson 	if (ret)
674925ca369SKent Gibson 		goto out_free_desc;
675925ca369SKent Gibson 
6766accc376SKent Gibson 	blocking_notifier_call_chain(&desc->gdev->notifier,
677925ca369SKent Gibson 				     GPIOLINE_CHANGED_REQUESTED, desc);
678925ca369SKent Gibson 
679925ca369SKent Gibson 	le->irq = gpiod_to_irq(desc);
680925ca369SKent Gibson 	if (le->irq <= 0) {
681925ca369SKent Gibson 		ret = -ENODEV;
682925ca369SKent Gibson 		goto out_free_desc;
683925ca369SKent Gibson 	}
684925ca369SKent Gibson 
685925ca369SKent Gibson 	if (eflags & GPIOEVENT_REQUEST_RISING_EDGE)
686925ca369SKent Gibson 		irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
687925ca369SKent Gibson 			IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
688925ca369SKent Gibson 	if (eflags & GPIOEVENT_REQUEST_FALLING_EDGE)
689925ca369SKent Gibson 		irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
690925ca369SKent Gibson 			IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
691925ca369SKent Gibson 	irqflags |= IRQF_ONESHOT;
692925ca369SKent Gibson 
693925ca369SKent Gibson 	INIT_KFIFO(le->events);
694925ca369SKent Gibson 	init_waitqueue_head(&le->wait);
695925ca369SKent Gibson 
696925ca369SKent Gibson 	/* Request a thread to read the events */
697925ca369SKent Gibson 	ret = request_threaded_irq(le->irq,
698925ca369SKent Gibson 				   lineevent_irq_handler,
699925ca369SKent Gibson 				   lineevent_irq_thread,
700925ca369SKent Gibson 				   irqflags,
701925ca369SKent Gibson 				   le->label,
702925ca369SKent Gibson 				   le);
703925ca369SKent Gibson 	if (ret)
704925ca369SKent Gibson 		goto out_free_desc;
705925ca369SKent Gibson 
706925ca369SKent Gibson 	fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
707925ca369SKent Gibson 	if (fd < 0) {
708925ca369SKent Gibson 		ret = fd;
709925ca369SKent Gibson 		goto out_free_irq;
710925ca369SKent Gibson 	}
711925ca369SKent Gibson 
712925ca369SKent Gibson 	file = anon_inode_getfile("gpio-event",
713925ca369SKent Gibson 				  &lineevent_fileops,
714925ca369SKent Gibson 				  le,
715925ca369SKent Gibson 				  O_RDONLY | O_CLOEXEC);
716925ca369SKent Gibson 	if (IS_ERR(file)) {
717925ca369SKent Gibson 		ret = PTR_ERR(file);
718925ca369SKent Gibson 		goto out_put_unused_fd;
719925ca369SKent Gibson 	}
720925ca369SKent Gibson 
721925ca369SKent Gibson 	eventreq.fd = fd;
722925ca369SKent Gibson 	if (copy_to_user(ip, &eventreq, sizeof(eventreq))) {
723925ca369SKent Gibson 		/*
724925ca369SKent Gibson 		 * fput() will trigger the release() callback, so do not go onto
725925ca369SKent Gibson 		 * the regular error cleanup path here.
726925ca369SKent Gibson 		 */
727925ca369SKent Gibson 		fput(file);
728925ca369SKent Gibson 		put_unused_fd(fd);
729925ca369SKent Gibson 		return -EFAULT;
730925ca369SKent Gibson 	}
731925ca369SKent Gibson 
732925ca369SKent Gibson 	fd_install(fd, file);
733925ca369SKent Gibson 
734925ca369SKent Gibson 	return 0;
735925ca369SKent Gibson 
736925ca369SKent Gibson out_put_unused_fd:
737925ca369SKent Gibson 	put_unused_fd(fd);
738925ca369SKent Gibson out_free_irq:
739925ca369SKent Gibson 	free_irq(le->irq, le);
740925ca369SKent Gibson out_free_desc:
741925ca369SKent Gibson 	gpiod_free(le->desc);
742925ca369SKent Gibson out_free_label:
743925ca369SKent Gibson 	kfree(le->label);
744925ca369SKent Gibson out_free_le:
745925ca369SKent Gibson 	kfree(le);
746925ca369SKent Gibson 	put_device(&gdev->dev);
747925ca369SKent Gibson 	return ret;
748925ca369SKent Gibson }
749925ca369SKent Gibson 
750925ca369SKent Gibson static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
751925ca369SKent Gibson 				  struct gpioline_info *info)
752925ca369SKent Gibson {
753925ca369SKent Gibson 	struct gpio_chip *gc = desc->gdev->chip;
754925ca369SKent Gibson 	bool ok_for_pinctrl;
755925ca369SKent Gibson 	unsigned long flags;
756925ca369SKent Gibson 
757925ca369SKent Gibson 	/*
758925ca369SKent Gibson 	 * This function takes a mutex so we must check this before taking
759925ca369SKent Gibson 	 * the spinlock.
760925ca369SKent Gibson 	 *
761925ca369SKent Gibson 	 * FIXME: find a non-racy way to retrieve this information. Maybe a
762925ca369SKent Gibson 	 * lock common to both frameworks?
763925ca369SKent Gibson 	 */
764925ca369SKent Gibson 	ok_for_pinctrl =
765925ca369SKent Gibson 		pinctrl_gpio_can_use_line(gc->base + info->line_offset);
766925ca369SKent Gibson 
767925ca369SKent Gibson 	spin_lock_irqsave(&gpio_lock, flags);
768925ca369SKent Gibson 
769925ca369SKent Gibson 	if (desc->name) {
770925ca369SKent Gibson 		strncpy(info->name, desc->name, sizeof(info->name));
771925ca369SKent Gibson 		info->name[sizeof(info->name) - 1] = '\0';
772925ca369SKent Gibson 	} else {
773925ca369SKent Gibson 		info->name[0] = '\0';
774925ca369SKent Gibson 	}
775925ca369SKent Gibson 
776925ca369SKent Gibson 	if (desc->label) {
777925ca369SKent Gibson 		strncpy(info->consumer, desc->label, sizeof(info->consumer));
778925ca369SKent Gibson 		info->consumer[sizeof(info->consumer) - 1] = '\0';
779925ca369SKent Gibson 	} else {
780925ca369SKent Gibson 		info->consumer[0] = '\0';
781925ca369SKent Gibson 	}
782925ca369SKent Gibson 
783925ca369SKent Gibson 	/*
784925ca369SKent Gibson 	 * Userspace only need to know that the kernel is using this GPIO so
785925ca369SKent Gibson 	 * it can't use it.
786925ca369SKent Gibson 	 */
787925ca369SKent Gibson 	info->flags = 0;
788925ca369SKent Gibson 	if (test_bit(FLAG_REQUESTED, &desc->flags) ||
789925ca369SKent Gibson 	    test_bit(FLAG_IS_HOGGED, &desc->flags) ||
790925ca369SKent Gibson 	    test_bit(FLAG_USED_AS_IRQ, &desc->flags) ||
791925ca369SKent Gibson 	    test_bit(FLAG_EXPORT, &desc->flags) ||
792925ca369SKent Gibson 	    test_bit(FLAG_SYSFS, &desc->flags) ||
793925ca369SKent Gibson 	    !ok_for_pinctrl)
794925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_KERNEL;
795925ca369SKent Gibson 	if (test_bit(FLAG_IS_OUT, &desc->flags))
796925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_IS_OUT;
797925ca369SKent Gibson 	if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
798925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_ACTIVE_LOW;
799925ca369SKent Gibson 	if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))
800925ca369SKent Gibson 		info->flags |= (GPIOLINE_FLAG_OPEN_DRAIN |
801925ca369SKent Gibson 				GPIOLINE_FLAG_IS_OUT);
802925ca369SKent Gibson 	if (test_bit(FLAG_OPEN_SOURCE, &desc->flags))
803925ca369SKent Gibson 		info->flags |= (GPIOLINE_FLAG_OPEN_SOURCE |
804925ca369SKent Gibson 				GPIOLINE_FLAG_IS_OUT);
805925ca369SKent Gibson 	if (test_bit(FLAG_BIAS_DISABLE, &desc->flags))
806925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_BIAS_DISABLE;
807925ca369SKent Gibson 	if (test_bit(FLAG_PULL_DOWN, &desc->flags))
808925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_BIAS_PULL_DOWN;
809925ca369SKent Gibson 	if (test_bit(FLAG_PULL_UP, &desc->flags))
810925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_BIAS_PULL_UP;
811925ca369SKent Gibson 
812925ca369SKent Gibson 	spin_unlock_irqrestore(&gpio_lock, flags);
813925ca369SKent Gibson }
814925ca369SKent Gibson 
815925ca369SKent Gibson struct gpio_chardev_data {
816925ca369SKent Gibson 	struct gpio_device *gdev;
817925ca369SKent Gibson 	wait_queue_head_t wait;
818925ca369SKent Gibson 	DECLARE_KFIFO(events, struct gpioline_info_changed, 32);
819925ca369SKent Gibson 	struct notifier_block lineinfo_changed_nb;
820925ca369SKent Gibson 	unsigned long *watched_lines;
821925ca369SKent Gibson };
822925ca369SKent Gibson 
823925ca369SKent Gibson /*
824925ca369SKent Gibson  * gpio_ioctl() - ioctl handler for the GPIO chardev
825925ca369SKent Gibson  */
82649bc5279SKent Gibson static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
827925ca369SKent Gibson {
828e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev = file->private_data;
829e2b781c5SKent Gibson 	struct gpio_device *gdev = cdev->gdev;
830925ca369SKent Gibson 	struct gpio_chip *gc = gdev->chip;
831925ca369SKent Gibson 	void __user *ip = (void __user *)arg;
832925ca369SKent Gibson 	struct gpio_desc *desc;
833925ca369SKent Gibson 	__u32 offset;
834925ca369SKent Gibson 
835925ca369SKent Gibson 	/* We fail any subsequent ioctl():s when the chip is gone */
836925ca369SKent Gibson 	if (!gc)
837925ca369SKent Gibson 		return -ENODEV;
838925ca369SKent Gibson 
839925ca369SKent Gibson 	/* Fill in the struct and pass to userspace */
840925ca369SKent Gibson 	if (cmd == GPIO_GET_CHIPINFO_IOCTL) {
841925ca369SKent Gibson 		struct gpiochip_info chipinfo;
842925ca369SKent Gibson 
843925ca369SKent Gibson 		memset(&chipinfo, 0, sizeof(chipinfo));
844925ca369SKent Gibson 
845925ca369SKent Gibson 		strncpy(chipinfo.name, dev_name(&gdev->dev),
846925ca369SKent Gibson 			sizeof(chipinfo.name));
847925ca369SKent Gibson 		chipinfo.name[sizeof(chipinfo.name)-1] = '\0';
848925ca369SKent Gibson 		strncpy(chipinfo.label, gdev->label,
849925ca369SKent Gibson 			sizeof(chipinfo.label));
850925ca369SKent Gibson 		chipinfo.label[sizeof(chipinfo.label)-1] = '\0';
851925ca369SKent Gibson 		chipinfo.lines = gdev->ngpio;
852925ca369SKent Gibson 		if (copy_to_user(ip, &chipinfo, sizeof(chipinfo)))
853925ca369SKent Gibson 			return -EFAULT;
854925ca369SKent Gibson 		return 0;
855925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEINFO_IOCTL) {
856925ca369SKent Gibson 		struct gpioline_info lineinfo;
857925ca369SKent Gibson 
858925ca369SKent Gibson 		if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
859925ca369SKent Gibson 			return -EFAULT;
860925ca369SKent Gibson 
8611bf7ba40SKent Gibson 		/* this doubles as a range check on line_offset */
862925ca369SKent Gibson 		desc = gpiochip_get_desc(gc, lineinfo.line_offset);
863925ca369SKent Gibson 		if (IS_ERR(desc))
864925ca369SKent Gibson 			return PTR_ERR(desc);
865925ca369SKent Gibson 
866925ca369SKent Gibson 		gpio_desc_to_lineinfo(desc, &lineinfo);
867925ca369SKent Gibson 
868925ca369SKent Gibson 		if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
869925ca369SKent Gibson 			return -EFAULT;
870925ca369SKent Gibson 		return 0;
871925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) {
872925ca369SKent Gibson 		return linehandle_create(gdev, ip);
873925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEEVENT_IOCTL) {
874925ca369SKent Gibson 		return lineevent_create(gdev, ip);
875925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) {
876925ca369SKent Gibson 		struct gpioline_info lineinfo;
877925ca369SKent Gibson 
878925ca369SKent Gibson 		if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
879925ca369SKent Gibson 			return -EFAULT;
880925ca369SKent Gibson 
8811bf7ba40SKent Gibson 		/* this doubles as a range check on line_offset */
882925ca369SKent Gibson 		desc = gpiochip_get_desc(gc, lineinfo.line_offset);
883925ca369SKent Gibson 		if (IS_ERR(desc))
884925ca369SKent Gibson 			return PTR_ERR(desc);
885925ca369SKent Gibson 
8861bf7ba40SKent Gibson 		if (test_and_set_bit(lineinfo.line_offset, cdev->watched_lines))
887925ca369SKent Gibson 			return -EBUSY;
888925ca369SKent Gibson 
889925ca369SKent Gibson 		gpio_desc_to_lineinfo(desc, &lineinfo);
890925ca369SKent Gibson 
891f30ef3e8SKent Gibson 		if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) {
8921bf7ba40SKent Gibson 			clear_bit(lineinfo.line_offset, cdev->watched_lines);
893925ca369SKent Gibson 			return -EFAULT;
894f30ef3e8SKent Gibson 		}
895925ca369SKent Gibson 
896925ca369SKent Gibson 		return 0;
897925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEINFO_UNWATCH_IOCTL) {
898925ca369SKent Gibson 		if (copy_from_user(&offset, ip, sizeof(offset)))
899925ca369SKent Gibson 			return -EFAULT;
900925ca369SKent Gibson 
9011bf7ba40SKent Gibson 		if (offset >= cdev->gdev->ngpio)
9021bf7ba40SKent Gibson 			return -EINVAL;
903925ca369SKent Gibson 
9041bf7ba40SKent Gibson 		if (!test_and_clear_bit(offset, cdev->watched_lines))
905925ca369SKent Gibson 			return -EBUSY;
906925ca369SKent Gibson 
907925ca369SKent Gibson 		return 0;
908925ca369SKent Gibson 	}
909925ca369SKent Gibson 	return -EINVAL;
910925ca369SKent Gibson }
911925ca369SKent Gibson 
912925ca369SKent Gibson #ifdef CONFIG_COMPAT
91349bc5279SKent Gibson static long gpio_ioctl_compat(struct file *file, unsigned int cmd,
914925ca369SKent Gibson 			      unsigned long arg)
915925ca369SKent Gibson {
91649bc5279SKent Gibson 	return gpio_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
917925ca369SKent Gibson }
918925ca369SKent Gibson #endif
919925ca369SKent Gibson 
920925ca369SKent Gibson static struct gpio_chardev_data *
921925ca369SKent Gibson to_gpio_chardev_data(struct notifier_block *nb)
922925ca369SKent Gibson {
923925ca369SKent Gibson 	return container_of(nb, struct gpio_chardev_data, lineinfo_changed_nb);
924925ca369SKent Gibson }
925925ca369SKent Gibson 
926925ca369SKent Gibson static int lineinfo_changed_notify(struct notifier_block *nb,
927925ca369SKent Gibson 				   unsigned long action, void *data)
928925ca369SKent Gibson {
929e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev = to_gpio_chardev_data(nb);
930925ca369SKent Gibson 	struct gpioline_info_changed chg;
931925ca369SKent Gibson 	struct gpio_desc *desc = data;
932925ca369SKent Gibson 	int ret;
933925ca369SKent Gibson 
934e2b781c5SKent Gibson 	if (!test_bit(gpio_chip_hwgpio(desc), cdev->watched_lines))
935925ca369SKent Gibson 		return NOTIFY_DONE;
936925ca369SKent Gibson 
937925ca369SKent Gibson 	memset(&chg, 0, sizeof(chg));
938925ca369SKent Gibson 	chg.info.line_offset = gpio_chip_hwgpio(desc);
939925ca369SKent Gibson 	chg.event_type = action;
940925ca369SKent Gibson 	chg.timestamp = ktime_get_ns();
941925ca369SKent Gibson 	gpio_desc_to_lineinfo(desc, &chg.info);
942925ca369SKent Gibson 
943e2b781c5SKent Gibson 	ret = kfifo_in_spinlocked(&cdev->events, &chg, 1, &cdev->wait.lock);
944925ca369SKent Gibson 	if (ret)
945e2b781c5SKent Gibson 		wake_up_poll(&cdev->wait, EPOLLIN);
946925ca369SKent Gibson 	else
947925ca369SKent Gibson 		pr_debug_ratelimited("lineinfo event FIFO is full - event dropped\n");
948925ca369SKent Gibson 
949925ca369SKent Gibson 	return NOTIFY_OK;
950925ca369SKent Gibson }
951925ca369SKent Gibson 
95249bc5279SKent Gibson static __poll_t lineinfo_watch_poll(struct file *file,
953925ca369SKent Gibson 				    struct poll_table_struct *pollt)
954925ca369SKent Gibson {
955e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev = file->private_data;
956925ca369SKent Gibson 	__poll_t events = 0;
957925ca369SKent Gibson 
958e2b781c5SKent Gibson 	poll_wait(file, &cdev->wait, pollt);
959925ca369SKent Gibson 
960e2b781c5SKent Gibson 	if (!kfifo_is_empty_spinlocked_noirqsave(&cdev->events,
961e2b781c5SKent Gibson 						 &cdev->wait.lock))
962925ca369SKent Gibson 		events = EPOLLIN | EPOLLRDNORM;
963925ca369SKent Gibson 
964925ca369SKent Gibson 	return events;
965925ca369SKent Gibson }
966925ca369SKent Gibson 
96749bc5279SKent Gibson static ssize_t lineinfo_watch_read(struct file *file, char __user *buf,
968925ca369SKent Gibson 				   size_t count, loff_t *off)
969925ca369SKent Gibson {
970e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev = file->private_data;
971925ca369SKent Gibson 	struct gpioline_info_changed event;
972925ca369SKent Gibson 	ssize_t bytes_read = 0;
973925ca369SKent Gibson 	int ret;
974925ca369SKent Gibson 
975925ca369SKent Gibson 	if (count < sizeof(event))
976925ca369SKent Gibson 		return -EINVAL;
977925ca369SKent Gibson 
978925ca369SKent Gibson 	do {
979e2b781c5SKent Gibson 		spin_lock(&cdev->wait.lock);
980e2b781c5SKent Gibson 		if (kfifo_is_empty(&cdev->events)) {
981925ca369SKent Gibson 			if (bytes_read) {
982e2b781c5SKent Gibson 				spin_unlock(&cdev->wait.lock);
983925ca369SKent Gibson 				return bytes_read;
984925ca369SKent Gibson 			}
985925ca369SKent Gibson 
98649bc5279SKent Gibson 			if (file->f_flags & O_NONBLOCK) {
987e2b781c5SKent Gibson 				spin_unlock(&cdev->wait.lock);
988925ca369SKent Gibson 				return -EAGAIN;
989925ca369SKent Gibson 			}
990925ca369SKent Gibson 
991e2b781c5SKent Gibson 			ret = wait_event_interruptible_locked(cdev->wait,
992e2b781c5SKent Gibson 					!kfifo_is_empty(&cdev->events));
993925ca369SKent Gibson 			if (ret) {
994e2b781c5SKent Gibson 				spin_unlock(&cdev->wait.lock);
995925ca369SKent Gibson 				return ret;
996925ca369SKent Gibson 			}
997925ca369SKent Gibson 		}
998925ca369SKent Gibson 
999e2b781c5SKent Gibson 		ret = kfifo_out(&cdev->events, &event, 1);
1000e2b781c5SKent Gibson 		spin_unlock(&cdev->wait.lock);
1001925ca369SKent Gibson 		if (ret != 1) {
1002925ca369SKent Gibson 			ret = -EIO;
1003925ca369SKent Gibson 			break;
1004925ca369SKent Gibson 			/* We should never get here. See lineevent_read(). */
1005925ca369SKent Gibson 		}
1006925ca369SKent Gibson 
1007925ca369SKent Gibson 		if (copy_to_user(buf + bytes_read, &event, sizeof(event)))
1008925ca369SKent Gibson 			return -EFAULT;
1009925ca369SKent Gibson 		bytes_read += sizeof(event);
1010925ca369SKent Gibson 	} while (count >= bytes_read + sizeof(event));
1011925ca369SKent Gibson 
1012925ca369SKent Gibson 	return bytes_read;
1013925ca369SKent Gibson }
1014925ca369SKent Gibson 
1015925ca369SKent Gibson /**
1016925ca369SKent Gibson  * gpio_chrdev_open() - open the chardev for ioctl operations
1017925ca369SKent Gibson  * @inode: inode for this chardev
101849bc5279SKent Gibson  * @file: file struct for storing private data
1019925ca369SKent Gibson  * Returns 0 on success
1020925ca369SKent Gibson  */
102149bc5279SKent Gibson static int gpio_chrdev_open(struct inode *inode, struct file *file)
1022925ca369SKent Gibson {
1023925ca369SKent Gibson 	struct gpio_device *gdev = container_of(inode->i_cdev,
1024925ca369SKent Gibson 						struct gpio_device, chrdev);
1025e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev;
1026925ca369SKent Gibson 	int ret = -ENOMEM;
1027925ca369SKent Gibson 
1028925ca369SKent Gibson 	/* Fail on open if the backing gpiochip is gone */
1029925ca369SKent Gibson 	if (!gdev->chip)
1030925ca369SKent Gibson 		return -ENODEV;
1031925ca369SKent Gibson 
1032e2b781c5SKent Gibson 	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
1033e2b781c5SKent Gibson 	if (!cdev)
1034925ca369SKent Gibson 		return -ENOMEM;
1035925ca369SKent Gibson 
1036e2b781c5SKent Gibson 	cdev->watched_lines = bitmap_zalloc(gdev->chip->ngpio, GFP_KERNEL);
1037e2b781c5SKent Gibson 	if (!cdev->watched_lines)
1038e2b781c5SKent Gibson 		goto out_free_cdev;
1039925ca369SKent Gibson 
1040e2b781c5SKent Gibson 	init_waitqueue_head(&cdev->wait);
1041e2b781c5SKent Gibson 	INIT_KFIFO(cdev->events);
1042e2b781c5SKent Gibson 	cdev->gdev = gdev;
1043925ca369SKent Gibson 
1044e2b781c5SKent Gibson 	cdev->lineinfo_changed_nb.notifier_call = lineinfo_changed_notify;
10456accc376SKent Gibson 	ret = blocking_notifier_chain_register(&gdev->notifier,
1046e2b781c5SKent Gibson 					       &cdev->lineinfo_changed_nb);
1047925ca369SKent Gibson 	if (ret)
1048925ca369SKent Gibson 		goto out_free_bitmap;
1049925ca369SKent Gibson 
1050925ca369SKent Gibson 	get_device(&gdev->dev);
1051e2b781c5SKent Gibson 	file->private_data = cdev;
1052925ca369SKent Gibson 
105349bc5279SKent Gibson 	ret = nonseekable_open(inode, file);
1054925ca369SKent Gibson 	if (ret)
1055925ca369SKent Gibson 		goto out_unregister_notifier;
1056925ca369SKent Gibson 
1057925ca369SKent Gibson 	return ret;
1058925ca369SKent Gibson 
1059925ca369SKent Gibson out_unregister_notifier:
10606accc376SKent Gibson 	blocking_notifier_chain_unregister(&gdev->notifier,
1061e2b781c5SKent Gibson 					   &cdev->lineinfo_changed_nb);
1062925ca369SKent Gibson out_free_bitmap:
1063e2b781c5SKent Gibson 	bitmap_free(cdev->watched_lines);
1064e2b781c5SKent Gibson out_free_cdev:
1065e2b781c5SKent Gibson 	kfree(cdev);
1066925ca369SKent Gibson 	return ret;
1067925ca369SKent Gibson }
1068925ca369SKent Gibson 
1069925ca369SKent Gibson /**
1070925ca369SKent Gibson  * gpio_chrdev_release() - close chardev after ioctl operations
1071925ca369SKent Gibson  * @inode: inode for this chardev
107249bc5279SKent Gibson  * @file: file struct for storing private data
1073925ca369SKent Gibson  * Returns 0 on success
1074925ca369SKent Gibson  */
107549bc5279SKent Gibson static int gpio_chrdev_release(struct inode *inode, struct file *file)
1076925ca369SKent Gibson {
1077e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev = file->private_data;
1078e2b781c5SKent Gibson 	struct gpio_device *gdev = cdev->gdev;
1079925ca369SKent Gibson 
1080e2b781c5SKent Gibson 	bitmap_free(cdev->watched_lines);
10816accc376SKent Gibson 	blocking_notifier_chain_unregister(&gdev->notifier,
1082e2b781c5SKent Gibson 					   &cdev->lineinfo_changed_nb);
1083925ca369SKent Gibson 	put_device(&gdev->dev);
1084e2b781c5SKent Gibson 	kfree(cdev);
1085925ca369SKent Gibson 
1086925ca369SKent Gibson 	return 0;
1087925ca369SKent Gibson }
1088925ca369SKent Gibson 
1089925ca369SKent Gibson static const struct file_operations gpio_fileops = {
1090925ca369SKent Gibson 	.release = gpio_chrdev_release,
1091925ca369SKent Gibson 	.open = gpio_chrdev_open,
1092925ca369SKent Gibson 	.poll = lineinfo_watch_poll,
1093925ca369SKent Gibson 	.read = lineinfo_watch_read,
1094925ca369SKent Gibson 	.owner = THIS_MODULE,
1095925ca369SKent Gibson 	.llseek = no_llseek,
1096925ca369SKent Gibson 	.unlocked_ioctl = gpio_ioctl,
1097925ca369SKent Gibson #ifdef CONFIG_COMPAT
1098925ca369SKent Gibson 	.compat_ioctl = gpio_ioctl_compat,
1099925ca369SKent Gibson #endif
1100925ca369SKent Gibson };
1101925ca369SKent Gibson 
1102925ca369SKent Gibson int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt)
1103925ca369SKent Gibson {
1104925ca369SKent Gibson 	int ret;
1105925ca369SKent Gibson 
1106925ca369SKent Gibson 	cdev_init(&gdev->chrdev, &gpio_fileops);
1107925ca369SKent Gibson 	gdev->chrdev.owner = THIS_MODULE;
1108925ca369SKent Gibson 	gdev->dev.devt = MKDEV(MAJOR(devt), gdev->id);
1109925ca369SKent Gibson 
1110925ca369SKent Gibson 	ret = cdev_device_add(&gdev->chrdev, &gdev->dev);
1111925ca369SKent Gibson 	if (ret)
1112925ca369SKent Gibson 		return ret;
1113925ca369SKent Gibson 
1114925ca369SKent Gibson 	chip_dbg(gdev->chip, "added GPIO chardev (%d:%d)\n",
1115925ca369SKent Gibson 		 MAJOR(devt), gdev->id);
1116925ca369SKent Gibson 
1117925ca369SKent Gibson 	return 0;
1118925ca369SKent Gibson }
1119925ca369SKent Gibson 
1120925ca369SKent Gibson void gpiolib_cdev_unregister(struct gpio_device *gdev)
1121925ca369SKent Gibson {
1122925ca369SKent Gibson 	cdev_device_del(&gdev->chrdev, &gdev->dev);
1123925ca369SKent Gibson }
1124