xref: /openbmc/linux/drivers/gpio/gpiolib-cdev.c (revision 0dc11e3ad353e19b1a119e3146c69c0930ecae5f)
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 
231883f9198SKent 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++)
236883f9198SKent Gibson 		if (lh->descs[i])
237925ca369SKent Gibson 			gpiod_free(lh->descs[i]);
238925ca369SKent Gibson 	kfree(lh->label);
239883f9198SKent Gibson 	put_device(&lh->gdev->dev);
240925ca369SKent Gibson 	kfree(lh);
241883f9198SKent Gibson }
242883f9198SKent Gibson 
243883f9198SKent Gibson static int linehandle_release(struct inode *inode, struct file *file)
244883f9198SKent Gibson {
245883f9198SKent 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;
264883f9198SKent 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 
295883f9198SKent Gibson 	lh->num_descs = handlereq.lines;
296883f9198SKent 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);
304883f9198SKent Gibson 			goto out_free_lh;
305925ca369SKent Gibson 		}
306925ca369SKent Gibson 
307925ca369SKent Gibson 		ret = gpiod_request(desc, lh->label);
308925ca369SKent Gibson 		if (ret)
309883f9198SKent 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)
315883f9198SKent 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)
326883f9198SKent Gibson 				goto out_free_lh;
327925ca369SKent Gibson 		} else if (lflags & GPIOHANDLE_REQUEST_INPUT) {
328925ca369SKent Gibson 			ret = gpiod_direction_input(desc);
329925ca369SKent Gibson 			if (ret)
330883f9198SKent 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;
343883f9198SKent 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:
376883f9198SKent 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 
48146824272SKent Gibson static void lineevent_free(struct lineevent_state *le)
482925ca369SKent Gibson {
48346824272SKent Gibson 	if (le->irq)
484925ca369SKent Gibson 		free_irq(le->irq, le);
48546824272SKent Gibson 	if (le->desc)
486925ca369SKent Gibson 		gpiod_free(le->desc);
487925ca369SKent Gibson 	kfree(le->label);
48846824272SKent Gibson 	put_device(&le->gdev->dev);
489925ca369SKent Gibson 	kfree(le);
49046824272SKent Gibson }
49146824272SKent Gibson 
49246824272SKent Gibson static int lineevent_release(struct inode *inode, struct file *file)
49346824272SKent Gibson {
49446824272SKent Gibson 	lineevent_free(file->private_data);
495925ca369SKent Gibson 	return 0;
496925ca369SKent Gibson }
497925ca369SKent Gibson 
49849bc5279SKent Gibson static long lineevent_ioctl(struct file *file, unsigned int cmd,
499925ca369SKent Gibson 			    unsigned long arg)
500925ca369SKent Gibson {
50149bc5279SKent Gibson 	struct lineevent_state *le = file->private_data;
502925ca369SKent Gibson 	void __user *ip = (void __user *)arg;
503925ca369SKent Gibson 	struct gpiohandle_data ghd;
504925ca369SKent Gibson 
505925ca369SKent Gibson 	/*
506925ca369SKent Gibson 	 * We can get the value for an event line but not set it,
507925ca369SKent Gibson 	 * because it is input by definition.
508925ca369SKent Gibson 	 */
509925ca369SKent Gibson 	if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) {
510925ca369SKent Gibson 		int val;
511925ca369SKent Gibson 
512925ca369SKent Gibson 		memset(&ghd, 0, sizeof(ghd));
513925ca369SKent Gibson 
514925ca369SKent Gibson 		val = gpiod_get_value_cansleep(le->desc);
515925ca369SKent Gibson 		if (val < 0)
516925ca369SKent Gibson 			return val;
517925ca369SKent Gibson 		ghd.values[0] = val;
518925ca369SKent Gibson 
519925ca369SKent Gibson 		if (copy_to_user(ip, &ghd, sizeof(ghd)))
520925ca369SKent Gibson 			return -EFAULT;
521925ca369SKent Gibson 
522925ca369SKent Gibson 		return 0;
523925ca369SKent Gibson 	}
524925ca369SKent Gibson 	return -EINVAL;
525925ca369SKent Gibson }
526925ca369SKent Gibson 
527925ca369SKent Gibson #ifdef CONFIG_COMPAT
52849bc5279SKent Gibson static long lineevent_ioctl_compat(struct file *file, unsigned int cmd,
529925ca369SKent Gibson 				   unsigned long arg)
530925ca369SKent Gibson {
53149bc5279SKent Gibson 	return lineevent_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
532925ca369SKent Gibson }
533925ca369SKent Gibson #endif
534925ca369SKent Gibson 
535925ca369SKent Gibson static const struct file_operations lineevent_fileops = {
536925ca369SKent Gibson 	.release = lineevent_release,
537925ca369SKent Gibson 	.read = lineevent_read,
538925ca369SKent Gibson 	.poll = lineevent_poll,
539925ca369SKent Gibson 	.owner = THIS_MODULE,
540925ca369SKent Gibson 	.llseek = noop_llseek,
541925ca369SKent Gibson 	.unlocked_ioctl = lineevent_ioctl,
542925ca369SKent Gibson #ifdef CONFIG_COMPAT
543925ca369SKent Gibson 	.compat_ioctl = lineevent_ioctl_compat,
544925ca369SKent Gibson #endif
545925ca369SKent Gibson };
546925ca369SKent Gibson 
547925ca369SKent Gibson static irqreturn_t lineevent_irq_thread(int irq, void *p)
548925ca369SKent Gibson {
549925ca369SKent Gibson 	struct lineevent_state *le = p;
550925ca369SKent Gibson 	struct gpioevent_data ge;
551925ca369SKent Gibson 	int ret;
552925ca369SKent Gibson 
553925ca369SKent Gibson 	/* Do not leak kernel stack to userspace */
554925ca369SKent Gibson 	memset(&ge, 0, sizeof(ge));
555925ca369SKent Gibson 
556925ca369SKent Gibson 	/*
557925ca369SKent Gibson 	 * We may be running from a nested threaded interrupt in which case
558925ca369SKent Gibson 	 * we didn't get the timestamp from lineevent_irq_handler().
559925ca369SKent Gibson 	 */
560925ca369SKent Gibson 	if (!le->timestamp)
561925ca369SKent Gibson 		ge.timestamp = ktime_get_ns();
562925ca369SKent Gibson 	else
563925ca369SKent Gibson 		ge.timestamp = le->timestamp;
564925ca369SKent Gibson 
565925ca369SKent Gibson 	if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE
566925ca369SKent Gibson 	    && le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
567925ca369SKent Gibson 		int level = gpiod_get_value_cansleep(le->desc);
568925ca369SKent Gibson 
569925ca369SKent Gibson 		if (level)
570925ca369SKent Gibson 			/* Emit low-to-high event */
571925ca369SKent Gibson 			ge.id = GPIOEVENT_EVENT_RISING_EDGE;
572925ca369SKent Gibson 		else
573925ca369SKent Gibson 			/* Emit high-to-low event */
574925ca369SKent Gibson 			ge.id = GPIOEVENT_EVENT_FALLING_EDGE;
575925ca369SKent Gibson 	} else if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE) {
576925ca369SKent Gibson 		/* Emit low-to-high event */
577925ca369SKent Gibson 		ge.id = GPIOEVENT_EVENT_RISING_EDGE;
578925ca369SKent Gibson 	} else if (le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
579925ca369SKent Gibson 		/* Emit high-to-low event */
580925ca369SKent Gibson 		ge.id = GPIOEVENT_EVENT_FALLING_EDGE;
581925ca369SKent Gibson 	} else {
582925ca369SKent Gibson 		return IRQ_NONE;
583925ca369SKent Gibson 	}
584925ca369SKent Gibson 
585925ca369SKent Gibson 	ret = kfifo_in_spinlocked_noirqsave(&le->events, &ge,
586925ca369SKent Gibson 					    1, &le->wait.lock);
587925ca369SKent Gibson 	if (ret)
588925ca369SKent Gibson 		wake_up_poll(&le->wait, EPOLLIN);
589925ca369SKent Gibson 	else
590925ca369SKent Gibson 		pr_debug_ratelimited("event FIFO is full - event dropped\n");
591925ca369SKent Gibson 
592925ca369SKent Gibson 	return IRQ_HANDLED;
593925ca369SKent Gibson }
594925ca369SKent Gibson 
595925ca369SKent Gibson static irqreturn_t lineevent_irq_handler(int irq, void *p)
596925ca369SKent Gibson {
597925ca369SKent Gibson 	struct lineevent_state *le = p;
598925ca369SKent Gibson 
599925ca369SKent Gibson 	/*
600925ca369SKent Gibson 	 * Just store the timestamp in hardirq context so we get it as
601925ca369SKent Gibson 	 * close in time as possible to the actual event.
602925ca369SKent Gibson 	 */
603925ca369SKent Gibson 	le->timestamp = ktime_get_ns();
604925ca369SKent Gibson 
605925ca369SKent Gibson 	return IRQ_WAKE_THREAD;
606925ca369SKent Gibson }
607925ca369SKent Gibson 
608925ca369SKent Gibson static int lineevent_create(struct gpio_device *gdev, void __user *ip)
609925ca369SKent Gibson {
610925ca369SKent Gibson 	struct gpioevent_request eventreq;
611925ca369SKent Gibson 	struct lineevent_state *le;
612925ca369SKent Gibson 	struct gpio_desc *desc;
613925ca369SKent Gibson 	struct file *file;
614925ca369SKent Gibson 	u32 offset;
615925ca369SKent Gibson 	u32 lflags;
616925ca369SKent Gibson 	u32 eflags;
617925ca369SKent Gibson 	int fd;
618925ca369SKent Gibson 	int ret;
61946824272SKent Gibson 	int irq, irqflags = 0;
620925ca369SKent Gibson 
621925ca369SKent Gibson 	if (copy_from_user(&eventreq, ip, sizeof(eventreq)))
622925ca369SKent Gibson 		return -EFAULT;
623925ca369SKent Gibson 
624925ca369SKent Gibson 	offset = eventreq.lineoffset;
625925ca369SKent Gibson 	lflags = eventreq.handleflags;
626925ca369SKent Gibson 	eflags = eventreq.eventflags;
627925ca369SKent Gibson 
628925ca369SKent Gibson 	desc = gpiochip_get_desc(gdev->chip, offset);
629925ca369SKent Gibson 	if (IS_ERR(desc))
630925ca369SKent Gibson 		return PTR_ERR(desc);
631925ca369SKent Gibson 
632925ca369SKent Gibson 	/* Return an error if a unknown flag is set */
633925ca369SKent Gibson 	if ((lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS) ||
634925ca369SKent Gibson 	    (eflags & ~GPIOEVENT_REQUEST_VALID_FLAGS))
635925ca369SKent Gibson 		return -EINVAL;
636925ca369SKent Gibson 
637925ca369SKent Gibson 	/* This is just wrong: we don't look for events on output lines */
638925ca369SKent Gibson 	if ((lflags & GPIOHANDLE_REQUEST_OUTPUT) ||
639925ca369SKent Gibson 	    (lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN) ||
640925ca369SKent Gibson 	    (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE))
641925ca369SKent Gibson 		return -EINVAL;
642925ca369SKent Gibson 
643925ca369SKent Gibson 	/* Only one bias flag can be set. */
644925ca369SKent Gibson 	if (((lflags & GPIOHANDLE_REQUEST_BIAS_DISABLE) &&
645925ca369SKent Gibson 	     (lflags & (GPIOHANDLE_REQUEST_BIAS_PULL_DOWN |
646925ca369SKent Gibson 			GPIOHANDLE_REQUEST_BIAS_PULL_UP))) ||
647925ca369SKent Gibson 	    ((lflags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN) &&
648925ca369SKent Gibson 	     (lflags & GPIOHANDLE_REQUEST_BIAS_PULL_UP)))
649925ca369SKent Gibson 		return -EINVAL;
650925ca369SKent Gibson 
651925ca369SKent Gibson 	le = kzalloc(sizeof(*le), GFP_KERNEL);
652925ca369SKent Gibson 	if (!le)
653925ca369SKent Gibson 		return -ENOMEM;
654925ca369SKent Gibson 	le->gdev = gdev;
655925ca369SKent Gibson 	get_device(&gdev->dev);
656925ca369SKent Gibson 
657925ca369SKent Gibson 	/* Make sure this is terminated */
658925ca369SKent Gibson 	eventreq.consumer_label[sizeof(eventreq.consumer_label)-1] = '\0';
659925ca369SKent Gibson 	if (strlen(eventreq.consumer_label)) {
660925ca369SKent Gibson 		le->label = kstrdup(eventreq.consumer_label,
661925ca369SKent Gibson 				    GFP_KERNEL);
662925ca369SKent Gibson 		if (!le->label) {
663925ca369SKent Gibson 			ret = -ENOMEM;
664925ca369SKent Gibson 			goto out_free_le;
665925ca369SKent Gibson 		}
666925ca369SKent Gibson 	}
667925ca369SKent Gibson 
668925ca369SKent Gibson 	ret = gpiod_request(desc, le->label);
669925ca369SKent Gibson 	if (ret)
67046824272SKent Gibson 		goto out_free_le;
671925ca369SKent Gibson 	le->desc = desc;
672925ca369SKent Gibson 	le->eflags = eflags;
673925ca369SKent Gibson 
674c274b58aSKent Gibson 	linehandle_flags_to_desc_flags(lflags, &desc->flags);
675925ca369SKent Gibson 
676925ca369SKent Gibson 	ret = gpiod_direction_input(desc);
677925ca369SKent Gibson 	if (ret)
67846824272SKent Gibson 		goto out_free_le;
679925ca369SKent Gibson 
6806accc376SKent Gibson 	blocking_notifier_call_chain(&desc->gdev->notifier,
681925ca369SKent Gibson 				     GPIOLINE_CHANGED_REQUESTED, desc);
682925ca369SKent Gibson 
68346824272SKent Gibson 	irq = gpiod_to_irq(desc);
68446824272SKent Gibson 	if (irq <= 0) {
685925ca369SKent Gibson 		ret = -ENODEV;
68646824272SKent Gibson 		goto out_free_le;
687925ca369SKent Gibson 	}
68846824272SKent Gibson 	le->irq = irq;
689925ca369SKent Gibson 
690925ca369SKent Gibson 	if (eflags & GPIOEVENT_REQUEST_RISING_EDGE)
691925ca369SKent Gibson 		irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
692925ca369SKent Gibson 			IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
693925ca369SKent Gibson 	if (eflags & GPIOEVENT_REQUEST_FALLING_EDGE)
694925ca369SKent Gibson 		irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
695925ca369SKent Gibson 			IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
696925ca369SKent Gibson 	irqflags |= IRQF_ONESHOT;
697925ca369SKent Gibson 
698925ca369SKent Gibson 	INIT_KFIFO(le->events);
699925ca369SKent Gibson 	init_waitqueue_head(&le->wait);
700925ca369SKent Gibson 
701925ca369SKent Gibson 	/* Request a thread to read the events */
702925ca369SKent Gibson 	ret = request_threaded_irq(le->irq,
703925ca369SKent Gibson 				   lineevent_irq_handler,
704925ca369SKent Gibson 				   lineevent_irq_thread,
705925ca369SKent Gibson 				   irqflags,
706925ca369SKent Gibson 				   le->label,
707925ca369SKent Gibson 				   le);
708925ca369SKent Gibson 	if (ret)
70946824272SKent Gibson 		goto out_free_le;
710925ca369SKent Gibson 
711925ca369SKent Gibson 	fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
712925ca369SKent Gibson 	if (fd < 0) {
713925ca369SKent Gibson 		ret = fd;
71446824272SKent Gibson 		goto out_free_le;
715925ca369SKent Gibson 	}
716925ca369SKent Gibson 
717925ca369SKent Gibson 	file = anon_inode_getfile("gpio-event",
718925ca369SKent Gibson 				  &lineevent_fileops,
719925ca369SKent Gibson 				  le,
720925ca369SKent Gibson 				  O_RDONLY | O_CLOEXEC);
721925ca369SKent Gibson 	if (IS_ERR(file)) {
722925ca369SKent Gibson 		ret = PTR_ERR(file);
723925ca369SKent Gibson 		goto out_put_unused_fd;
724925ca369SKent Gibson 	}
725925ca369SKent Gibson 
726925ca369SKent Gibson 	eventreq.fd = fd;
727925ca369SKent Gibson 	if (copy_to_user(ip, &eventreq, sizeof(eventreq))) {
728925ca369SKent Gibson 		/*
729925ca369SKent Gibson 		 * fput() will trigger the release() callback, so do not go onto
730925ca369SKent Gibson 		 * the regular error cleanup path here.
731925ca369SKent Gibson 		 */
732925ca369SKent Gibson 		fput(file);
733925ca369SKent Gibson 		put_unused_fd(fd);
734925ca369SKent Gibson 		return -EFAULT;
735925ca369SKent Gibson 	}
736925ca369SKent Gibson 
737925ca369SKent Gibson 	fd_install(fd, file);
738925ca369SKent Gibson 
739925ca369SKent Gibson 	return 0;
740925ca369SKent Gibson 
741925ca369SKent Gibson out_put_unused_fd:
742925ca369SKent Gibson 	put_unused_fd(fd);
743925ca369SKent Gibson out_free_le:
74446824272SKent Gibson 	lineevent_free(le);
745925ca369SKent Gibson 	return ret;
746925ca369SKent Gibson }
747925ca369SKent Gibson 
748925ca369SKent Gibson static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
749925ca369SKent Gibson 				  struct gpioline_info *info)
750925ca369SKent Gibson {
751925ca369SKent Gibson 	struct gpio_chip *gc = desc->gdev->chip;
752925ca369SKent Gibson 	bool ok_for_pinctrl;
753925ca369SKent Gibson 	unsigned long flags;
754925ca369SKent Gibson 
755*0dc11e3aSKent Gibson 	info->line_offset = gpio_chip_hwgpio(desc);
756*0dc11e3aSKent 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.event_type = action;
939925ca369SKent Gibson 	chg.timestamp = ktime_get_ns();
940925ca369SKent Gibson 	gpio_desc_to_lineinfo(desc, &chg.info);
941925ca369SKent Gibson 
942e2b781c5SKent Gibson 	ret = kfifo_in_spinlocked(&cdev->events, &chg, 1, &cdev->wait.lock);
943925ca369SKent Gibson 	if (ret)
944e2b781c5SKent Gibson 		wake_up_poll(&cdev->wait, EPOLLIN);
945925ca369SKent Gibson 	else
946925ca369SKent Gibson 		pr_debug_ratelimited("lineinfo event FIFO is full - event dropped\n");
947925ca369SKent Gibson 
948925ca369SKent Gibson 	return NOTIFY_OK;
949925ca369SKent Gibson }
950925ca369SKent Gibson 
95149bc5279SKent Gibson static __poll_t lineinfo_watch_poll(struct file *file,
952925ca369SKent Gibson 				    struct poll_table_struct *pollt)
953925ca369SKent Gibson {
954e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev = file->private_data;
955925ca369SKent Gibson 	__poll_t events = 0;
956925ca369SKent Gibson 
957e2b781c5SKent Gibson 	poll_wait(file, &cdev->wait, pollt);
958925ca369SKent Gibson 
959e2b781c5SKent Gibson 	if (!kfifo_is_empty_spinlocked_noirqsave(&cdev->events,
960e2b781c5SKent Gibson 						 &cdev->wait.lock))
961925ca369SKent Gibson 		events = EPOLLIN | EPOLLRDNORM;
962925ca369SKent Gibson 
963925ca369SKent Gibson 	return events;
964925ca369SKent Gibson }
965925ca369SKent Gibson 
96649bc5279SKent Gibson static ssize_t lineinfo_watch_read(struct file *file, char __user *buf,
967925ca369SKent Gibson 				   size_t count, loff_t *off)
968925ca369SKent Gibson {
969e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev = file->private_data;
970925ca369SKent Gibson 	struct gpioline_info_changed event;
971925ca369SKent Gibson 	ssize_t bytes_read = 0;
972925ca369SKent Gibson 	int ret;
973925ca369SKent Gibson 
974925ca369SKent Gibson 	if (count < sizeof(event))
975925ca369SKent Gibson 		return -EINVAL;
976925ca369SKent Gibson 
977925ca369SKent Gibson 	do {
978e2b781c5SKent Gibson 		spin_lock(&cdev->wait.lock);
979e2b781c5SKent Gibson 		if (kfifo_is_empty(&cdev->events)) {
980925ca369SKent Gibson 			if (bytes_read) {
981e2b781c5SKent Gibson 				spin_unlock(&cdev->wait.lock);
982925ca369SKent Gibson 				return bytes_read;
983925ca369SKent Gibson 			}
984925ca369SKent Gibson 
98549bc5279SKent Gibson 			if (file->f_flags & O_NONBLOCK) {
986e2b781c5SKent Gibson 				spin_unlock(&cdev->wait.lock);
987925ca369SKent Gibson 				return -EAGAIN;
988925ca369SKent Gibson 			}
989925ca369SKent Gibson 
990e2b781c5SKent Gibson 			ret = wait_event_interruptible_locked(cdev->wait,
991e2b781c5SKent Gibson 					!kfifo_is_empty(&cdev->events));
992925ca369SKent Gibson 			if (ret) {
993e2b781c5SKent Gibson 				spin_unlock(&cdev->wait.lock);
994925ca369SKent Gibson 				return ret;
995925ca369SKent Gibson 			}
996925ca369SKent Gibson 		}
997925ca369SKent Gibson 
998e2b781c5SKent Gibson 		ret = kfifo_out(&cdev->events, &event, 1);
999e2b781c5SKent Gibson 		spin_unlock(&cdev->wait.lock);
1000925ca369SKent Gibson 		if (ret != 1) {
1001925ca369SKent Gibson 			ret = -EIO;
1002925ca369SKent Gibson 			break;
1003925ca369SKent Gibson 			/* We should never get here. See lineevent_read(). */
1004925ca369SKent Gibson 		}
1005925ca369SKent Gibson 
1006925ca369SKent Gibson 		if (copy_to_user(buf + bytes_read, &event, sizeof(event)))
1007925ca369SKent Gibson 			return -EFAULT;
1008925ca369SKent Gibson 		bytes_read += sizeof(event);
1009925ca369SKent Gibson 	} while (count >= bytes_read + sizeof(event));
1010925ca369SKent Gibson 
1011925ca369SKent Gibson 	return bytes_read;
1012925ca369SKent Gibson }
1013925ca369SKent Gibson 
1014925ca369SKent Gibson /**
1015925ca369SKent Gibson  * gpio_chrdev_open() - open the chardev for ioctl operations
1016925ca369SKent Gibson  * @inode: inode for this chardev
101749bc5279SKent Gibson  * @file: file struct for storing private data
1018925ca369SKent Gibson  * Returns 0 on success
1019925ca369SKent Gibson  */
102049bc5279SKent Gibson static int gpio_chrdev_open(struct inode *inode, struct file *file)
1021925ca369SKent Gibson {
1022925ca369SKent Gibson 	struct gpio_device *gdev = container_of(inode->i_cdev,
1023925ca369SKent Gibson 						struct gpio_device, chrdev);
1024e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev;
1025925ca369SKent Gibson 	int ret = -ENOMEM;
1026925ca369SKent Gibson 
1027925ca369SKent Gibson 	/* Fail on open if the backing gpiochip is gone */
1028925ca369SKent Gibson 	if (!gdev->chip)
1029925ca369SKent Gibson 		return -ENODEV;
1030925ca369SKent Gibson 
1031e2b781c5SKent Gibson 	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
1032e2b781c5SKent Gibson 	if (!cdev)
1033925ca369SKent Gibson 		return -ENOMEM;
1034925ca369SKent Gibson 
1035e2b781c5SKent Gibson 	cdev->watched_lines = bitmap_zalloc(gdev->chip->ngpio, GFP_KERNEL);
1036e2b781c5SKent Gibson 	if (!cdev->watched_lines)
1037e2b781c5SKent Gibson 		goto out_free_cdev;
1038925ca369SKent Gibson 
1039e2b781c5SKent Gibson 	init_waitqueue_head(&cdev->wait);
1040e2b781c5SKent Gibson 	INIT_KFIFO(cdev->events);
1041e2b781c5SKent Gibson 	cdev->gdev = gdev;
1042925ca369SKent Gibson 
1043e2b781c5SKent Gibson 	cdev->lineinfo_changed_nb.notifier_call = lineinfo_changed_notify;
10446accc376SKent Gibson 	ret = blocking_notifier_chain_register(&gdev->notifier,
1045e2b781c5SKent Gibson 					       &cdev->lineinfo_changed_nb);
1046925ca369SKent Gibson 	if (ret)
1047925ca369SKent Gibson 		goto out_free_bitmap;
1048925ca369SKent Gibson 
1049925ca369SKent Gibson 	get_device(&gdev->dev);
1050e2b781c5SKent Gibson 	file->private_data = cdev;
1051925ca369SKent Gibson 
105249bc5279SKent Gibson 	ret = nonseekable_open(inode, file);
1053925ca369SKent Gibson 	if (ret)
1054925ca369SKent Gibson 		goto out_unregister_notifier;
1055925ca369SKent Gibson 
1056925ca369SKent Gibson 	return ret;
1057925ca369SKent Gibson 
1058925ca369SKent Gibson out_unregister_notifier:
10596accc376SKent Gibson 	blocking_notifier_chain_unregister(&gdev->notifier,
1060e2b781c5SKent Gibson 					   &cdev->lineinfo_changed_nb);
1061925ca369SKent Gibson out_free_bitmap:
1062e2b781c5SKent Gibson 	bitmap_free(cdev->watched_lines);
1063e2b781c5SKent Gibson out_free_cdev:
1064e2b781c5SKent Gibson 	kfree(cdev);
1065925ca369SKent Gibson 	return ret;
1066925ca369SKent Gibson }
1067925ca369SKent Gibson 
1068925ca369SKent Gibson /**
1069925ca369SKent Gibson  * gpio_chrdev_release() - close chardev after ioctl operations
1070925ca369SKent Gibson  * @inode: inode for this chardev
107149bc5279SKent Gibson  * @file: file struct for storing private data
1072925ca369SKent Gibson  * Returns 0 on success
1073925ca369SKent Gibson  */
107449bc5279SKent Gibson static int gpio_chrdev_release(struct inode *inode, struct file *file)
1075925ca369SKent Gibson {
1076e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev = file->private_data;
1077e2b781c5SKent Gibson 	struct gpio_device *gdev = cdev->gdev;
1078925ca369SKent Gibson 
1079e2b781c5SKent Gibson 	bitmap_free(cdev->watched_lines);
10806accc376SKent Gibson 	blocking_notifier_chain_unregister(&gdev->notifier,
1081e2b781c5SKent Gibson 					   &cdev->lineinfo_changed_nb);
1082925ca369SKent Gibson 	put_device(&gdev->dev);
1083e2b781c5SKent Gibson 	kfree(cdev);
1084925ca369SKent Gibson 
1085925ca369SKent Gibson 	return 0;
1086925ca369SKent Gibson }
1087925ca369SKent Gibson 
1088925ca369SKent Gibson static const struct file_operations gpio_fileops = {
1089925ca369SKent Gibson 	.release = gpio_chrdev_release,
1090925ca369SKent Gibson 	.open = gpio_chrdev_open,
1091925ca369SKent Gibson 	.poll = lineinfo_watch_poll,
1092925ca369SKent Gibson 	.read = lineinfo_watch_read,
1093925ca369SKent Gibson 	.owner = THIS_MODULE,
1094925ca369SKent Gibson 	.llseek = no_llseek,
1095925ca369SKent Gibson 	.unlocked_ioctl = gpio_ioctl,
1096925ca369SKent Gibson #ifdef CONFIG_COMPAT
1097925ca369SKent Gibson 	.compat_ioctl = gpio_ioctl_compat,
1098925ca369SKent Gibson #endif
1099925ca369SKent Gibson };
1100925ca369SKent Gibson 
1101925ca369SKent Gibson int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt)
1102925ca369SKent Gibson {
1103925ca369SKent Gibson 	int ret;
1104925ca369SKent Gibson 
1105925ca369SKent Gibson 	cdev_init(&gdev->chrdev, &gpio_fileops);
1106925ca369SKent Gibson 	gdev->chrdev.owner = THIS_MODULE;
1107925ca369SKent Gibson 	gdev->dev.devt = MKDEV(MAJOR(devt), gdev->id);
1108925ca369SKent Gibson 
1109925ca369SKent Gibson 	ret = cdev_device_add(&gdev->chrdev, &gdev->dev);
1110925ca369SKent Gibson 	if (ret)
1111925ca369SKent Gibson 		return ret;
1112925ca369SKent Gibson 
1113925ca369SKent Gibson 	chip_dbg(gdev->chip, "added GPIO chardev (%d:%d)\n",
1114925ca369SKent Gibson 		 MAJOR(devt), gdev->id);
1115925ca369SKent Gibson 
1116925ca369SKent Gibson 	return 0;
1117925ca369SKent Gibson }
1118925ca369SKent Gibson 
1119925ca369SKent Gibson void gpiolib_cdev_unregister(struct gpio_device *gdev)
1120925ca369SKent Gibson {
1121925ca369SKent Gibson 	cdev_device_del(&gdev->chrdev, &gdev->dev);
1122925ca369SKent Gibson }
1123