xref: /openbmc/linux/drivers/gpio/gpiolib-cdev.c (revision e2b781c5f0dd45f632b3e15bbca702d1d140fce7)
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 
23149bc5279SKent Gibson static int linehandle_release(struct inode *inode, struct file *file)
232925ca369SKent Gibson {
23349bc5279SKent Gibson 	struct linehandle_state *lh = file->private_data;
234925ca369SKent Gibson 	struct gpio_device *gdev = lh->gdev;
235925ca369SKent Gibson 	int i;
236925ca369SKent Gibson 
23752b7b596SKent Gibson 	for (i = 0; i < lh->num_descs; i++)
238925ca369SKent Gibson 		gpiod_free(lh->descs[i]);
239925ca369SKent Gibson 	kfree(lh->label);
240925ca369SKent Gibson 	kfree(lh);
241925ca369SKent Gibson 	put_device(&gdev->dev);
242925ca369SKent Gibson 	return 0;
243925ca369SKent Gibson }
244925ca369SKent Gibson 
245925ca369SKent Gibson static const struct file_operations linehandle_fileops = {
246925ca369SKent Gibson 	.release = linehandle_release,
247925ca369SKent Gibson 	.owner = THIS_MODULE,
248925ca369SKent Gibson 	.llseek = noop_llseek,
249925ca369SKent Gibson 	.unlocked_ioctl = linehandle_ioctl,
250925ca369SKent Gibson #ifdef CONFIG_COMPAT
251925ca369SKent Gibson 	.compat_ioctl = linehandle_ioctl_compat,
252925ca369SKent Gibson #endif
253925ca369SKent Gibson };
254925ca369SKent Gibson 
255925ca369SKent Gibson static int linehandle_create(struct gpio_device *gdev, void __user *ip)
256925ca369SKent Gibson {
257925ca369SKent Gibson 	struct gpiohandle_request handlereq;
258925ca369SKent Gibson 	struct linehandle_state *lh;
259925ca369SKent Gibson 	struct file *file;
260925ca369SKent Gibson 	int fd, i, count = 0, ret;
261925ca369SKent Gibson 	u32 lflags;
262925ca369SKent Gibson 
263925ca369SKent Gibson 	if (copy_from_user(&handlereq, ip, sizeof(handlereq)))
264925ca369SKent Gibson 		return -EFAULT;
265925ca369SKent Gibson 	if ((handlereq.lines == 0) || (handlereq.lines > GPIOHANDLES_MAX))
266925ca369SKent Gibson 		return -EINVAL;
267925ca369SKent Gibson 
268925ca369SKent Gibson 	lflags = handlereq.flags;
269925ca369SKent Gibson 
270925ca369SKent Gibson 	ret = linehandle_validate_flags(lflags);
271925ca369SKent Gibson 	if (ret)
272925ca369SKent Gibson 		return ret;
273925ca369SKent Gibson 
274925ca369SKent Gibson 	lh = kzalloc(sizeof(*lh), GFP_KERNEL);
275925ca369SKent Gibson 	if (!lh)
276925ca369SKent Gibson 		return -ENOMEM;
277925ca369SKent Gibson 	lh->gdev = gdev;
278925ca369SKent Gibson 	get_device(&gdev->dev);
279925ca369SKent Gibson 
280925ca369SKent Gibson 	/* Make sure this is terminated */
281925ca369SKent Gibson 	handlereq.consumer_label[sizeof(handlereq.consumer_label)-1] = '\0';
282925ca369SKent Gibson 	if (strlen(handlereq.consumer_label)) {
283925ca369SKent Gibson 		lh->label = kstrdup(handlereq.consumer_label,
284925ca369SKent Gibson 				    GFP_KERNEL);
285925ca369SKent Gibson 		if (!lh->label) {
286925ca369SKent Gibson 			ret = -ENOMEM;
287925ca369SKent Gibson 			goto out_free_lh;
288925ca369SKent Gibson 		}
289925ca369SKent Gibson 	}
290925ca369SKent Gibson 
291925ca369SKent Gibson 	/* Request each GPIO */
292925ca369SKent Gibson 	for (i = 0; i < handlereq.lines; i++) {
293925ca369SKent Gibson 		u32 offset = handlereq.lineoffsets[i];
294925ca369SKent Gibson 		struct gpio_desc *desc = gpiochip_get_desc(gdev->chip, offset);
295925ca369SKent Gibson 
296925ca369SKent Gibson 		if (IS_ERR(desc)) {
297925ca369SKent Gibson 			ret = PTR_ERR(desc);
298925ca369SKent Gibson 			goto out_free_descs;
299925ca369SKent Gibson 		}
300925ca369SKent Gibson 
301925ca369SKent Gibson 		ret = gpiod_request(desc, lh->label);
302925ca369SKent Gibson 		if (ret)
303925ca369SKent Gibson 			goto out_free_descs;
304925ca369SKent Gibson 		lh->descs[i] = desc;
305925ca369SKent Gibson 		count = i + 1;
306c274b58aSKent Gibson 		linehandle_flags_to_desc_flags(handlereq.flags, &desc->flags);
307925ca369SKent Gibson 
308925ca369SKent Gibson 		ret = gpiod_set_transitory(desc, false);
309925ca369SKent Gibson 		if (ret < 0)
310925ca369SKent Gibson 			goto out_free_descs;
311925ca369SKent Gibson 
312925ca369SKent Gibson 		/*
313925ca369SKent Gibson 		 * Lines have to be requested explicitly for input
314925ca369SKent Gibson 		 * or output, else the line will be treated "as is".
315925ca369SKent Gibson 		 */
316925ca369SKent Gibson 		if (lflags & GPIOHANDLE_REQUEST_OUTPUT) {
317925ca369SKent Gibson 			int val = !!handlereq.default_values[i];
318925ca369SKent Gibson 
319925ca369SKent Gibson 			ret = gpiod_direction_output(desc, val);
320925ca369SKent Gibson 			if (ret)
321925ca369SKent Gibson 				goto out_free_descs;
322925ca369SKent Gibson 		} else if (lflags & GPIOHANDLE_REQUEST_INPUT) {
323925ca369SKent Gibson 			ret = gpiod_direction_input(desc);
324925ca369SKent Gibson 			if (ret)
325925ca369SKent Gibson 				goto out_free_descs;
326925ca369SKent Gibson 		}
327925ca369SKent Gibson 
3286accc376SKent Gibson 		blocking_notifier_call_chain(&desc->gdev->notifier,
329925ca369SKent Gibson 					     GPIOLINE_CHANGED_REQUESTED, desc);
330925ca369SKent Gibson 
331925ca369SKent Gibson 		dev_dbg(&gdev->dev, "registered chardev handle for line %d\n",
332925ca369SKent Gibson 			offset);
333925ca369SKent Gibson 	}
33452b7b596SKent Gibson 	lh->num_descs = handlereq.lines;
335925ca369SKent Gibson 
336925ca369SKent Gibson 	fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
337925ca369SKent Gibson 	if (fd < 0) {
338925ca369SKent Gibson 		ret = fd;
339925ca369SKent Gibson 		goto out_free_descs;
340925ca369SKent Gibson 	}
341925ca369SKent Gibson 
342925ca369SKent Gibson 	file = anon_inode_getfile("gpio-linehandle",
343925ca369SKent Gibson 				  &linehandle_fileops,
344925ca369SKent Gibson 				  lh,
345925ca369SKent Gibson 				  O_RDONLY | O_CLOEXEC);
346925ca369SKent Gibson 	if (IS_ERR(file)) {
347925ca369SKent Gibson 		ret = PTR_ERR(file);
348925ca369SKent Gibson 		goto out_put_unused_fd;
349925ca369SKent Gibson 	}
350925ca369SKent Gibson 
351925ca369SKent Gibson 	handlereq.fd = fd;
352925ca369SKent Gibson 	if (copy_to_user(ip, &handlereq, sizeof(handlereq))) {
353925ca369SKent Gibson 		/*
354925ca369SKent Gibson 		 * fput() will trigger the release() callback, so do not go onto
355925ca369SKent Gibson 		 * the regular error cleanup path here.
356925ca369SKent Gibson 		 */
357925ca369SKent Gibson 		fput(file);
358925ca369SKent Gibson 		put_unused_fd(fd);
359925ca369SKent Gibson 		return -EFAULT;
360925ca369SKent Gibson 	}
361925ca369SKent Gibson 
362925ca369SKent Gibson 	fd_install(fd, file);
363925ca369SKent Gibson 
364925ca369SKent Gibson 	dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n",
36552b7b596SKent Gibson 		lh->num_descs);
366925ca369SKent Gibson 
367925ca369SKent Gibson 	return 0;
368925ca369SKent Gibson 
369925ca369SKent Gibson out_put_unused_fd:
370925ca369SKent Gibson 	put_unused_fd(fd);
371925ca369SKent Gibson out_free_descs:
372925ca369SKent Gibson 	for (i = 0; i < count; i++)
373925ca369SKent Gibson 		gpiod_free(lh->descs[i]);
374925ca369SKent Gibson 	kfree(lh->label);
375925ca369SKent Gibson out_free_lh:
376925ca369SKent Gibson 	kfree(lh);
377925ca369SKent Gibson 	put_device(&gdev->dev);
378925ca369SKent Gibson 	return ret;
379925ca369SKent Gibson }
380925ca369SKent Gibson 
381925ca369SKent Gibson /*
382925ca369SKent Gibson  * GPIO line event management
383925ca369SKent Gibson  */
384925ca369SKent Gibson 
385925ca369SKent Gibson /**
386925ca369SKent Gibson  * struct lineevent_state - contains the state of a userspace event
387925ca369SKent Gibson  * @gdev: the GPIO device the event pertains to
388925ca369SKent Gibson  * @label: consumer label used to tag descriptors
389925ca369SKent Gibson  * @desc: the GPIO descriptor held by this event
390925ca369SKent Gibson  * @eflags: the event flags this line was requested with
391925ca369SKent Gibson  * @irq: the interrupt that trigger in response to events on this GPIO
392925ca369SKent Gibson  * @wait: wait queue that handles blocking reads of events
393925ca369SKent Gibson  * @events: KFIFO for the GPIO events
394925ca369SKent Gibson  * @timestamp: cache for the timestamp storing it between hardirq
395925ca369SKent Gibson  * and IRQ thread, used to bring the timestamp close to the actual
396925ca369SKent Gibson  * event
397925ca369SKent Gibson  */
398925ca369SKent Gibson struct lineevent_state {
399925ca369SKent Gibson 	struct gpio_device *gdev;
400925ca369SKent Gibson 	const char *label;
401925ca369SKent Gibson 	struct gpio_desc *desc;
402925ca369SKent Gibson 	u32 eflags;
403925ca369SKent Gibson 	int irq;
404925ca369SKent Gibson 	wait_queue_head_t wait;
405925ca369SKent Gibson 	DECLARE_KFIFO(events, struct gpioevent_data, 16);
406925ca369SKent Gibson 	u64 timestamp;
407925ca369SKent Gibson };
408925ca369SKent Gibson 
409925ca369SKent Gibson #define GPIOEVENT_REQUEST_VALID_FLAGS \
410925ca369SKent Gibson 	(GPIOEVENT_REQUEST_RISING_EDGE | \
411925ca369SKent Gibson 	GPIOEVENT_REQUEST_FALLING_EDGE)
412925ca369SKent Gibson 
41349bc5279SKent Gibson static __poll_t lineevent_poll(struct file *file,
414925ca369SKent Gibson 			       struct poll_table_struct *wait)
415925ca369SKent Gibson {
41649bc5279SKent Gibson 	struct lineevent_state *le = file->private_data;
417925ca369SKent Gibson 	__poll_t events = 0;
418925ca369SKent Gibson 
41949bc5279SKent Gibson 	poll_wait(file, &le->wait, wait);
420925ca369SKent Gibson 
421925ca369SKent Gibson 	if (!kfifo_is_empty_spinlocked_noirqsave(&le->events, &le->wait.lock))
422925ca369SKent Gibson 		events = EPOLLIN | EPOLLRDNORM;
423925ca369SKent Gibson 
424925ca369SKent Gibson 	return events;
425925ca369SKent Gibson }
426925ca369SKent Gibson 
427925ca369SKent Gibson 
42849bc5279SKent Gibson static ssize_t lineevent_read(struct file *file,
429925ca369SKent Gibson 			      char __user *buf,
430925ca369SKent Gibson 			      size_t count,
431925ca369SKent Gibson 			      loff_t *f_ps)
432925ca369SKent Gibson {
43349bc5279SKent Gibson 	struct lineevent_state *le = file->private_data;
434925ca369SKent Gibson 	struct gpioevent_data ge;
435925ca369SKent Gibson 	ssize_t bytes_read = 0;
436925ca369SKent Gibson 	int ret;
437925ca369SKent Gibson 
438925ca369SKent Gibson 	if (count < sizeof(ge))
439925ca369SKent Gibson 		return -EINVAL;
440925ca369SKent Gibson 
441925ca369SKent Gibson 	do {
442925ca369SKent Gibson 		spin_lock(&le->wait.lock);
443925ca369SKent Gibson 		if (kfifo_is_empty(&le->events)) {
444925ca369SKent Gibson 			if (bytes_read) {
445925ca369SKent Gibson 				spin_unlock(&le->wait.lock);
446925ca369SKent Gibson 				return bytes_read;
447925ca369SKent Gibson 			}
448925ca369SKent Gibson 
44949bc5279SKent Gibson 			if (file->f_flags & O_NONBLOCK) {
450925ca369SKent Gibson 				spin_unlock(&le->wait.lock);
451925ca369SKent Gibson 				return -EAGAIN;
452925ca369SKent Gibson 			}
453925ca369SKent Gibson 
454925ca369SKent Gibson 			ret = wait_event_interruptible_locked(le->wait,
455925ca369SKent Gibson 					!kfifo_is_empty(&le->events));
456925ca369SKent Gibson 			if (ret) {
457925ca369SKent Gibson 				spin_unlock(&le->wait.lock);
458925ca369SKent Gibson 				return ret;
459925ca369SKent Gibson 			}
460925ca369SKent Gibson 		}
461925ca369SKent Gibson 
462925ca369SKent Gibson 		ret = kfifo_out(&le->events, &ge, 1);
463925ca369SKent Gibson 		spin_unlock(&le->wait.lock);
464925ca369SKent Gibson 		if (ret != 1) {
465925ca369SKent Gibson 			/*
466925ca369SKent Gibson 			 * This should never happen - we were holding the lock
467925ca369SKent Gibson 			 * from the moment we learned the fifo is no longer
468925ca369SKent Gibson 			 * empty until now.
469925ca369SKent Gibson 			 */
470925ca369SKent Gibson 			ret = -EIO;
471925ca369SKent Gibson 			break;
472925ca369SKent Gibson 		}
473925ca369SKent Gibson 
474925ca369SKent Gibson 		if (copy_to_user(buf + bytes_read, &ge, sizeof(ge)))
475925ca369SKent Gibson 			return -EFAULT;
476925ca369SKent Gibson 		bytes_read += sizeof(ge);
477925ca369SKent Gibson 	} while (count >= bytes_read + sizeof(ge));
478925ca369SKent Gibson 
479925ca369SKent Gibson 	return bytes_read;
480925ca369SKent Gibson }
481925ca369SKent Gibson 
48249bc5279SKent Gibson static int lineevent_release(struct inode *inode, struct file *file)
483925ca369SKent Gibson {
48449bc5279SKent Gibson 	struct lineevent_state *le = file->private_data;
485925ca369SKent Gibson 	struct gpio_device *gdev = le->gdev;
486925ca369SKent Gibson 
487925ca369SKent Gibson 	free_irq(le->irq, le);
488925ca369SKent Gibson 	gpiod_free(le->desc);
489925ca369SKent Gibson 	kfree(le->label);
490925ca369SKent Gibson 	kfree(le);
491925ca369SKent Gibson 	put_device(&gdev->dev);
492925ca369SKent Gibson 	return 0;
493925ca369SKent Gibson }
494925ca369SKent Gibson 
49549bc5279SKent Gibson static long lineevent_ioctl(struct file *file, unsigned int cmd,
496925ca369SKent Gibson 			    unsigned long arg)
497925ca369SKent Gibson {
49849bc5279SKent Gibson 	struct lineevent_state *le = file->private_data;
499925ca369SKent Gibson 	void __user *ip = (void __user *)arg;
500925ca369SKent Gibson 	struct gpiohandle_data ghd;
501925ca369SKent Gibson 
502925ca369SKent Gibson 	/*
503925ca369SKent Gibson 	 * We can get the value for an event line but not set it,
504925ca369SKent Gibson 	 * because it is input by definition.
505925ca369SKent Gibson 	 */
506925ca369SKent Gibson 	if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) {
507925ca369SKent Gibson 		int val;
508925ca369SKent Gibson 
509925ca369SKent Gibson 		memset(&ghd, 0, sizeof(ghd));
510925ca369SKent Gibson 
511925ca369SKent Gibson 		val = gpiod_get_value_cansleep(le->desc);
512925ca369SKent Gibson 		if (val < 0)
513925ca369SKent Gibson 			return val;
514925ca369SKent Gibson 		ghd.values[0] = val;
515925ca369SKent Gibson 
516925ca369SKent Gibson 		if (copy_to_user(ip, &ghd, sizeof(ghd)))
517925ca369SKent Gibson 			return -EFAULT;
518925ca369SKent Gibson 
519925ca369SKent Gibson 		return 0;
520925ca369SKent Gibson 	}
521925ca369SKent Gibson 	return -EINVAL;
522925ca369SKent Gibson }
523925ca369SKent Gibson 
524925ca369SKent Gibson #ifdef CONFIG_COMPAT
52549bc5279SKent Gibson static long lineevent_ioctl_compat(struct file *file, unsigned int cmd,
526925ca369SKent Gibson 				   unsigned long arg)
527925ca369SKent Gibson {
52849bc5279SKent Gibson 	return lineevent_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
529925ca369SKent Gibson }
530925ca369SKent Gibson #endif
531925ca369SKent Gibson 
532925ca369SKent Gibson static const struct file_operations lineevent_fileops = {
533925ca369SKent Gibson 	.release = lineevent_release,
534925ca369SKent Gibson 	.read = lineevent_read,
535925ca369SKent Gibson 	.poll = lineevent_poll,
536925ca369SKent Gibson 	.owner = THIS_MODULE,
537925ca369SKent Gibson 	.llseek = noop_llseek,
538925ca369SKent Gibson 	.unlocked_ioctl = lineevent_ioctl,
539925ca369SKent Gibson #ifdef CONFIG_COMPAT
540925ca369SKent Gibson 	.compat_ioctl = lineevent_ioctl_compat,
541925ca369SKent Gibson #endif
542925ca369SKent Gibson };
543925ca369SKent Gibson 
544925ca369SKent Gibson static irqreturn_t lineevent_irq_thread(int irq, void *p)
545925ca369SKent Gibson {
546925ca369SKent Gibson 	struct lineevent_state *le = p;
547925ca369SKent Gibson 	struct gpioevent_data ge;
548925ca369SKent Gibson 	int ret;
549925ca369SKent Gibson 
550925ca369SKent Gibson 	/* Do not leak kernel stack to userspace */
551925ca369SKent Gibson 	memset(&ge, 0, sizeof(ge));
552925ca369SKent Gibson 
553925ca369SKent Gibson 	/*
554925ca369SKent Gibson 	 * We may be running from a nested threaded interrupt in which case
555925ca369SKent Gibson 	 * we didn't get the timestamp from lineevent_irq_handler().
556925ca369SKent Gibson 	 */
557925ca369SKent Gibson 	if (!le->timestamp)
558925ca369SKent Gibson 		ge.timestamp = ktime_get_ns();
559925ca369SKent Gibson 	else
560925ca369SKent Gibson 		ge.timestamp = le->timestamp;
561925ca369SKent Gibson 
562925ca369SKent Gibson 	if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE
563925ca369SKent Gibson 	    && le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
564925ca369SKent Gibson 		int level = gpiod_get_value_cansleep(le->desc);
565925ca369SKent Gibson 
566925ca369SKent Gibson 		if (level)
567925ca369SKent Gibson 			/* Emit low-to-high event */
568925ca369SKent Gibson 			ge.id = GPIOEVENT_EVENT_RISING_EDGE;
569925ca369SKent Gibson 		else
570925ca369SKent Gibson 			/* Emit high-to-low event */
571925ca369SKent Gibson 			ge.id = GPIOEVENT_EVENT_FALLING_EDGE;
572925ca369SKent Gibson 	} else if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE) {
573925ca369SKent Gibson 		/* Emit low-to-high event */
574925ca369SKent Gibson 		ge.id = GPIOEVENT_EVENT_RISING_EDGE;
575925ca369SKent Gibson 	} else if (le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
576925ca369SKent Gibson 		/* Emit high-to-low event */
577925ca369SKent Gibson 		ge.id = GPIOEVENT_EVENT_FALLING_EDGE;
578925ca369SKent Gibson 	} else {
579925ca369SKent Gibson 		return IRQ_NONE;
580925ca369SKent Gibson 	}
581925ca369SKent Gibson 
582925ca369SKent Gibson 	ret = kfifo_in_spinlocked_noirqsave(&le->events, &ge,
583925ca369SKent Gibson 					    1, &le->wait.lock);
584925ca369SKent Gibson 	if (ret)
585925ca369SKent Gibson 		wake_up_poll(&le->wait, EPOLLIN);
586925ca369SKent Gibson 	else
587925ca369SKent Gibson 		pr_debug_ratelimited("event FIFO is full - event dropped\n");
588925ca369SKent Gibson 
589925ca369SKent Gibson 	return IRQ_HANDLED;
590925ca369SKent Gibson }
591925ca369SKent Gibson 
592925ca369SKent Gibson static irqreturn_t lineevent_irq_handler(int irq, void *p)
593925ca369SKent Gibson {
594925ca369SKent Gibson 	struct lineevent_state *le = p;
595925ca369SKent Gibson 
596925ca369SKent Gibson 	/*
597925ca369SKent Gibson 	 * Just store the timestamp in hardirq context so we get it as
598925ca369SKent Gibson 	 * close in time as possible to the actual event.
599925ca369SKent Gibson 	 */
600925ca369SKent Gibson 	le->timestamp = ktime_get_ns();
601925ca369SKent Gibson 
602925ca369SKent Gibson 	return IRQ_WAKE_THREAD;
603925ca369SKent Gibson }
604925ca369SKent Gibson 
605925ca369SKent Gibson static int lineevent_create(struct gpio_device *gdev, void __user *ip)
606925ca369SKent Gibson {
607925ca369SKent Gibson 	struct gpioevent_request eventreq;
608925ca369SKent Gibson 	struct lineevent_state *le;
609925ca369SKent Gibson 	struct gpio_desc *desc;
610925ca369SKent Gibson 	struct file *file;
611925ca369SKent Gibson 	u32 offset;
612925ca369SKent Gibson 	u32 lflags;
613925ca369SKent Gibson 	u32 eflags;
614925ca369SKent Gibson 	int fd;
615925ca369SKent Gibson 	int ret;
616925ca369SKent Gibson 	int irqflags = 0;
617925ca369SKent Gibson 
618925ca369SKent Gibson 	if (copy_from_user(&eventreq, ip, sizeof(eventreq)))
619925ca369SKent Gibson 		return -EFAULT;
620925ca369SKent Gibson 
621925ca369SKent Gibson 	offset = eventreq.lineoffset;
622925ca369SKent Gibson 	lflags = eventreq.handleflags;
623925ca369SKent Gibson 	eflags = eventreq.eventflags;
624925ca369SKent Gibson 
625925ca369SKent Gibson 	desc = gpiochip_get_desc(gdev->chip, offset);
626925ca369SKent Gibson 	if (IS_ERR(desc))
627925ca369SKent Gibson 		return PTR_ERR(desc);
628925ca369SKent Gibson 
629925ca369SKent Gibson 	/* Return an error if a unknown flag is set */
630925ca369SKent Gibson 	if ((lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS) ||
631925ca369SKent Gibson 	    (eflags & ~GPIOEVENT_REQUEST_VALID_FLAGS))
632925ca369SKent Gibson 		return -EINVAL;
633925ca369SKent Gibson 
634925ca369SKent Gibson 	/* This is just wrong: we don't look for events on output lines */
635925ca369SKent Gibson 	if ((lflags & GPIOHANDLE_REQUEST_OUTPUT) ||
636925ca369SKent Gibson 	    (lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN) ||
637925ca369SKent Gibson 	    (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE))
638925ca369SKent Gibson 		return -EINVAL;
639925ca369SKent Gibson 
640925ca369SKent Gibson 	/* Only one bias flag can be set. */
641925ca369SKent Gibson 	if (((lflags & GPIOHANDLE_REQUEST_BIAS_DISABLE) &&
642925ca369SKent Gibson 	     (lflags & (GPIOHANDLE_REQUEST_BIAS_PULL_DOWN |
643925ca369SKent Gibson 			GPIOHANDLE_REQUEST_BIAS_PULL_UP))) ||
644925ca369SKent Gibson 	    ((lflags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN) &&
645925ca369SKent Gibson 	     (lflags & GPIOHANDLE_REQUEST_BIAS_PULL_UP)))
646925ca369SKent Gibson 		return -EINVAL;
647925ca369SKent Gibson 
648925ca369SKent Gibson 	le = kzalloc(sizeof(*le), GFP_KERNEL);
649925ca369SKent Gibson 	if (!le)
650925ca369SKent Gibson 		return -ENOMEM;
651925ca369SKent Gibson 	le->gdev = gdev;
652925ca369SKent Gibson 	get_device(&gdev->dev);
653925ca369SKent Gibson 
654925ca369SKent Gibson 	/* Make sure this is terminated */
655925ca369SKent Gibson 	eventreq.consumer_label[sizeof(eventreq.consumer_label)-1] = '\0';
656925ca369SKent Gibson 	if (strlen(eventreq.consumer_label)) {
657925ca369SKent Gibson 		le->label = kstrdup(eventreq.consumer_label,
658925ca369SKent Gibson 				    GFP_KERNEL);
659925ca369SKent Gibson 		if (!le->label) {
660925ca369SKent Gibson 			ret = -ENOMEM;
661925ca369SKent Gibson 			goto out_free_le;
662925ca369SKent Gibson 		}
663925ca369SKent Gibson 	}
664925ca369SKent Gibson 
665925ca369SKent Gibson 	ret = gpiod_request(desc, le->label);
666925ca369SKent Gibson 	if (ret)
667925ca369SKent Gibson 		goto out_free_label;
668925ca369SKent Gibson 	le->desc = desc;
669925ca369SKent Gibson 	le->eflags = eflags;
670925ca369SKent Gibson 
671c274b58aSKent Gibson 	linehandle_flags_to_desc_flags(lflags, &desc->flags);
672925ca369SKent Gibson 
673925ca369SKent Gibson 	ret = gpiod_direction_input(desc);
674925ca369SKent Gibson 	if (ret)
675925ca369SKent Gibson 		goto out_free_desc;
676925ca369SKent Gibson 
6776accc376SKent Gibson 	blocking_notifier_call_chain(&desc->gdev->notifier,
678925ca369SKent Gibson 				     GPIOLINE_CHANGED_REQUESTED, desc);
679925ca369SKent Gibson 
680925ca369SKent Gibson 	le->irq = gpiod_to_irq(desc);
681925ca369SKent Gibson 	if (le->irq <= 0) {
682925ca369SKent Gibson 		ret = -ENODEV;
683925ca369SKent Gibson 		goto out_free_desc;
684925ca369SKent Gibson 	}
685925ca369SKent Gibson 
686925ca369SKent Gibson 	if (eflags & GPIOEVENT_REQUEST_RISING_EDGE)
687925ca369SKent Gibson 		irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
688925ca369SKent Gibson 			IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
689925ca369SKent Gibson 	if (eflags & GPIOEVENT_REQUEST_FALLING_EDGE)
690925ca369SKent Gibson 		irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
691925ca369SKent Gibson 			IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
692925ca369SKent Gibson 	irqflags |= IRQF_ONESHOT;
693925ca369SKent Gibson 
694925ca369SKent Gibson 	INIT_KFIFO(le->events);
695925ca369SKent Gibson 	init_waitqueue_head(&le->wait);
696925ca369SKent Gibson 
697925ca369SKent Gibson 	/* Request a thread to read the events */
698925ca369SKent Gibson 	ret = request_threaded_irq(le->irq,
699925ca369SKent Gibson 				   lineevent_irq_handler,
700925ca369SKent Gibson 				   lineevent_irq_thread,
701925ca369SKent Gibson 				   irqflags,
702925ca369SKent Gibson 				   le->label,
703925ca369SKent Gibson 				   le);
704925ca369SKent Gibson 	if (ret)
705925ca369SKent Gibson 		goto out_free_desc;
706925ca369SKent Gibson 
707925ca369SKent Gibson 	fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
708925ca369SKent Gibson 	if (fd < 0) {
709925ca369SKent Gibson 		ret = fd;
710925ca369SKent Gibson 		goto out_free_irq;
711925ca369SKent Gibson 	}
712925ca369SKent Gibson 
713925ca369SKent Gibson 	file = anon_inode_getfile("gpio-event",
714925ca369SKent Gibson 				  &lineevent_fileops,
715925ca369SKent Gibson 				  le,
716925ca369SKent Gibson 				  O_RDONLY | O_CLOEXEC);
717925ca369SKent Gibson 	if (IS_ERR(file)) {
718925ca369SKent Gibson 		ret = PTR_ERR(file);
719925ca369SKent Gibson 		goto out_put_unused_fd;
720925ca369SKent Gibson 	}
721925ca369SKent Gibson 
722925ca369SKent Gibson 	eventreq.fd = fd;
723925ca369SKent Gibson 	if (copy_to_user(ip, &eventreq, sizeof(eventreq))) {
724925ca369SKent Gibson 		/*
725925ca369SKent Gibson 		 * fput() will trigger the release() callback, so do not go onto
726925ca369SKent Gibson 		 * the regular error cleanup path here.
727925ca369SKent Gibson 		 */
728925ca369SKent Gibson 		fput(file);
729925ca369SKent Gibson 		put_unused_fd(fd);
730925ca369SKent Gibson 		return -EFAULT;
731925ca369SKent Gibson 	}
732925ca369SKent Gibson 
733925ca369SKent Gibson 	fd_install(fd, file);
734925ca369SKent Gibson 
735925ca369SKent Gibson 	return 0;
736925ca369SKent Gibson 
737925ca369SKent Gibson out_put_unused_fd:
738925ca369SKent Gibson 	put_unused_fd(fd);
739925ca369SKent Gibson out_free_irq:
740925ca369SKent Gibson 	free_irq(le->irq, le);
741925ca369SKent Gibson out_free_desc:
742925ca369SKent Gibson 	gpiod_free(le->desc);
743925ca369SKent Gibson out_free_label:
744925ca369SKent Gibson 	kfree(le->label);
745925ca369SKent Gibson out_free_le:
746925ca369SKent Gibson 	kfree(le);
747925ca369SKent Gibson 	put_device(&gdev->dev);
748925ca369SKent Gibson 	return ret;
749925ca369SKent Gibson }
750925ca369SKent Gibson 
751925ca369SKent Gibson static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
752925ca369SKent Gibson 				  struct gpioline_info *info)
753925ca369SKent Gibson {
754925ca369SKent Gibson 	struct gpio_chip *gc = desc->gdev->chip;
755925ca369SKent Gibson 	bool ok_for_pinctrl;
756925ca369SKent Gibson 	unsigned long flags;
757925ca369SKent Gibson 
758925ca369SKent Gibson 	/*
759925ca369SKent Gibson 	 * This function takes a mutex so we must check this before taking
760925ca369SKent Gibson 	 * the spinlock.
761925ca369SKent Gibson 	 *
762925ca369SKent Gibson 	 * FIXME: find a non-racy way to retrieve this information. Maybe a
763925ca369SKent Gibson 	 * lock common to both frameworks?
764925ca369SKent Gibson 	 */
765925ca369SKent Gibson 	ok_for_pinctrl =
766925ca369SKent Gibson 		pinctrl_gpio_can_use_line(gc->base + info->line_offset);
767925ca369SKent Gibson 
768925ca369SKent Gibson 	spin_lock_irqsave(&gpio_lock, flags);
769925ca369SKent Gibson 
770925ca369SKent Gibson 	if (desc->name) {
771925ca369SKent Gibson 		strncpy(info->name, desc->name, sizeof(info->name));
772925ca369SKent Gibson 		info->name[sizeof(info->name) - 1] = '\0';
773925ca369SKent Gibson 	} else {
774925ca369SKent Gibson 		info->name[0] = '\0';
775925ca369SKent Gibson 	}
776925ca369SKent Gibson 
777925ca369SKent Gibson 	if (desc->label) {
778925ca369SKent Gibson 		strncpy(info->consumer, desc->label, sizeof(info->consumer));
779925ca369SKent Gibson 		info->consumer[sizeof(info->consumer) - 1] = '\0';
780925ca369SKent Gibson 	} else {
781925ca369SKent Gibson 		info->consumer[0] = '\0';
782925ca369SKent Gibson 	}
783925ca369SKent Gibson 
784925ca369SKent Gibson 	/*
785925ca369SKent Gibson 	 * Userspace only need to know that the kernel is using this GPIO so
786925ca369SKent Gibson 	 * it can't use it.
787925ca369SKent Gibson 	 */
788925ca369SKent Gibson 	info->flags = 0;
789925ca369SKent Gibson 	if (test_bit(FLAG_REQUESTED, &desc->flags) ||
790925ca369SKent Gibson 	    test_bit(FLAG_IS_HOGGED, &desc->flags) ||
791925ca369SKent Gibson 	    test_bit(FLAG_USED_AS_IRQ, &desc->flags) ||
792925ca369SKent Gibson 	    test_bit(FLAG_EXPORT, &desc->flags) ||
793925ca369SKent Gibson 	    test_bit(FLAG_SYSFS, &desc->flags) ||
794925ca369SKent Gibson 	    !ok_for_pinctrl)
795925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_KERNEL;
796925ca369SKent Gibson 	if (test_bit(FLAG_IS_OUT, &desc->flags))
797925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_IS_OUT;
798925ca369SKent Gibson 	if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
799925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_ACTIVE_LOW;
800925ca369SKent Gibson 	if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))
801925ca369SKent Gibson 		info->flags |= (GPIOLINE_FLAG_OPEN_DRAIN |
802925ca369SKent Gibson 				GPIOLINE_FLAG_IS_OUT);
803925ca369SKent Gibson 	if (test_bit(FLAG_OPEN_SOURCE, &desc->flags))
804925ca369SKent Gibson 		info->flags |= (GPIOLINE_FLAG_OPEN_SOURCE |
805925ca369SKent Gibson 				GPIOLINE_FLAG_IS_OUT);
806925ca369SKent Gibson 	if (test_bit(FLAG_BIAS_DISABLE, &desc->flags))
807925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_BIAS_DISABLE;
808925ca369SKent Gibson 	if (test_bit(FLAG_PULL_DOWN, &desc->flags))
809925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_BIAS_PULL_DOWN;
810925ca369SKent Gibson 	if (test_bit(FLAG_PULL_UP, &desc->flags))
811925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_BIAS_PULL_UP;
812925ca369SKent Gibson 
813925ca369SKent Gibson 	spin_unlock_irqrestore(&gpio_lock, flags);
814925ca369SKent Gibson }
815925ca369SKent Gibson 
816925ca369SKent Gibson struct gpio_chardev_data {
817925ca369SKent Gibson 	struct gpio_device *gdev;
818925ca369SKent Gibson 	wait_queue_head_t wait;
819925ca369SKent Gibson 	DECLARE_KFIFO(events, struct gpioline_info_changed, 32);
820925ca369SKent Gibson 	struct notifier_block lineinfo_changed_nb;
821925ca369SKent Gibson 	unsigned long *watched_lines;
822925ca369SKent Gibson };
823925ca369SKent Gibson 
824925ca369SKent Gibson /*
825925ca369SKent Gibson  * gpio_ioctl() - ioctl handler for the GPIO chardev
826925ca369SKent Gibson  */
82749bc5279SKent Gibson static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
828925ca369SKent Gibson {
829*e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev = file->private_data;
830*e2b781c5SKent Gibson 	struct gpio_device *gdev = cdev->gdev;
831925ca369SKent Gibson 	struct gpio_chip *gc = gdev->chip;
832925ca369SKent Gibson 	void __user *ip = (void __user *)arg;
833925ca369SKent Gibson 	struct gpio_desc *desc;
834925ca369SKent Gibson 	__u32 offset;
835925ca369SKent Gibson 	int hwgpio;
836925ca369SKent Gibson 
837925ca369SKent Gibson 	/* We fail any subsequent ioctl():s when the chip is gone */
838925ca369SKent Gibson 	if (!gc)
839925ca369SKent Gibson 		return -ENODEV;
840925ca369SKent Gibson 
841925ca369SKent Gibson 	/* Fill in the struct and pass to userspace */
842925ca369SKent Gibson 	if (cmd == GPIO_GET_CHIPINFO_IOCTL) {
843925ca369SKent Gibson 		struct gpiochip_info chipinfo;
844925ca369SKent Gibson 
845925ca369SKent Gibson 		memset(&chipinfo, 0, sizeof(chipinfo));
846925ca369SKent Gibson 
847925ca369SKent Gibson 		strncpy(chipinfo.name, dev_name(&gdev->dev),
848925ca369SKent Gibson 			sizeof(chipinfo.name));
849925ca369SKent Gibson 		chipinfo.name[sizeof(chipinfo.name)-1] = '\0';
850925ca369SKent Gibson 		strncpy(chipinfo.label, gdev->label,
851925ca369SKent Gibson 			sizeof(chipinfo.label));
852925ca369SKent Gibson 		chipinfo.label[sizeof(chipinfo.label)-1] = '\0';
853925ca369SKent Gibson 		chipinfo.lines = gdev->ngpio;
854925ca369SKent Gibson 		if (copy_to_user(ip, &chipinfo, sizeof(chipinfo)))
855925ca369SKent Gibson 			return -EFAULT;
856925ca369SKent Gibson 		return 0;
857925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEINFO_IOCTL) {
858925ca369SKent Gibson 		struct gpioline_info lineinfo;
859925ca369SKent Gibson 
860925ca369SKent Gibson 		if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
861925ca369SKent Gibson 			return -EFAULT;
862925ca369SKent Gibson 
863925ca369SKent Gibson 		desc = gpiochip_get_desc(gc, lineinfo.line_offset);
864925ca369SKent Gibson 		if (IS_ERR(desc))
865925ca369SKent Gibson 			return PTR_ERR(desc);
866925ca369SKent Gibson 
867925ca369SKent Gibson 		hwgpio = gpio_chip_hwgpio(desc);
868925ca369SKent Gibson 
869925ca369SKent Gibson 		gpio_desc_to_lineinfo(desc, &lineinfo);
870925ca369SKent Gibson 
871925ca369SKent Gibson 		if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
872925ca369SKent Gibson 			return -EFAULT;
873925ca369SKent Gibson 		return 0;
874925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) {
875925ca369SKent Gibson 		return linehandle_create(gdev, ip);
876925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEEVENT_IOCTL) {
877925ca369SKent Gibson 		return lineevent_create(gdev, ip);
878925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) {
879925ca369SKent Gibson 		struct gpioline_info lineinfo;
880925ca369SKent Gibson 
881925ca369SKent Gibson 		if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
882925ca369SKent Gibson 			return -EFAULT;
883925ca369SKent Gibson 
884925ca369SKent Gibson 		desc = gpiochip_get_desc(gc, lineinfo.line_offset);
885925ca369SKent Gibson 		if (IS_ERR(desc))
886925ca369SKent Gibson 			return PTR_ERR(desc);
887925ca369SKent Gibson 
888925ca369SKent Gibson 		hwgpio = gpio_chip_hwgpio(desc);
889925ca369SKent Gibson 
890*e2b781c5SKent Gibson 		if (test_bit(hwgpio, cdev->watched_lines))
891925ca369SKent Gibson 			return -EBUSY;
892925ca369SKent Gibson 
893925ca369SKent Gibson 		gpio_desc_to_lineinfo(desc, &lineinfo);
894925ca369SKent Gibson 
895925ca369SKent Gibson 		if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
896925ca369SKent Gibson 			return -EFAULT;
897925ca369SKent Gibson 
898*e2b781c5SKent Gibson 		set_bit(hwgpio, cdev->watched_lines);
899925ca369SKent Gibson 		return 0;
900925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEINFO_UNWATCH_IOCTL) {
901925ca369SKent Gibson 		if (copy_from_user(&offset, ip, sizeof(offset)))
902925ca369SKent Gibson 			return -EFAULT;
903925ca369SKent Gibson 
904925ca369SKent Gibson 		desc = gpiochip_get_desc(gc, offset);
905925ca369SKent Gibson 		if (IS_ERR(desc))
906925ca369SKent Gibson 			return PTR_ERR(desc);
907925ca369SKent Gibson 
908925ca369SKent Gibson 		hwgpio = gpio_chip_hwgpio(desc);
909925ca369SKent Gibson 
910*e2b781c5SKent Gibson 		if (!test_bit(hwgpio, cdev->watched_lines))
911925ca369SKent Gibson 			return -EBUSY;
912925ca369SKent Gibson 
913*e2b781c5SKent Gibson 		clear_bit(hwgpio, cdev->watched_lines);
914925ca369SKent Gibson 		return 0;
915925ca369SKent Gibson 	}
916925ca369SKent Gibson 	return -EINVAL;
917925ca369SKent Gibson }
918925ca369SKent Gibson 
919925ca369SKent Gibson #ifdef CONFIG_COMPAT
92049bc5279SKent Gibson static long gpio_ioctl_compat(struct file *file, unsigned int cmd,
921925ca369SKent Gibson 			      unsigned long arg)
922925ca369SKent Gibson {
92349bc5279SKent Gibson 	return gpio_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
924925ca369SKent Gibson }
925925ca369SKent Gibson #endif
926925ca369SKent Gibson 
927925ca369SKent Gibson static struct gpio_chardev_data *
928925ca369SKent Gibson to_gpio_chardev_data(struct notifier_block *nb)
929925ca369SKent Gibson {
930925ca369SKent Gibson 	return container_of(nb, struct gpio_chardev_data, lineinfo_changed_nb);
931925ca369SKent Gibson }
932925ca369SKent Gibson 
933925ca369SKent Gibson static int lineinfo_changed_notify(struct notifier_block *nb,
934925ca369SKent Gibson 				   unsigned long action, void *data)
935925ca369SKent Gibson {
936*e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev = to_gpio_chardev_data(nb);
937925ca369SKent Gibson 	struct gpioline_info_changed chg;
938925ca369SKent Gibson 	struct gpio_desc *desc = data;
939925ca369SKent Gibson 	int ret;
940925ca369SKent Gibson 
941*e2b781c5SKent Gibson 	if (!test_bit(gpio_chip_hwgpio(desc), cdev->watched_lines))
942925ca369SKent Gibson 		return NOTIFY_DONE;
943925ca369SKent Gibson 
944925ca369SKent Gibson 	memset(&chg, 0, sizeof(chg));
945925ca369SKent Gibson 	chg.info.line_offset = gpio_chip_hwgpio(desc);
946925ca369SKent Gibson 	chg.event_type = action;
947925ca369SKent Gibson 	chg.timestamp = ktime_get_ns();
948925ca369SKent Gibson 	gpio_desc_to_lineinfo(desc, &chg.info);
949925ca369SKent Gibson 
950*e2b781c5SKent Gibson 	ret = kfifo_in_spinlocked(&cdev->events, &chg, 1, &cdev->wait.lock);
951925ca369SKent Gibson 	if (ret)
952*e2b781c5SKent Gibson 		wake_up_poll(&cdev->wait, EPOLLIN);
953925ca369SKent Gibson 	else
954925ca369SKent Gibson 		pr_debug_ratelimited("lineinfo event FIFO is full - event dropped\n");
955925ca369SKent Gibson 
956925ca369SKent Gibson 	return NOTIFY_OK;
957925ca369SKent Gibson }
958925ca369SKent Gibson 
95949bc5279SKent Gibson static __poll_t lineinfo_watch_poll(struct file *file,
960925ca369SKent Gibson 				    struct poll_table_struct *pollt)
961925ca369SKent Gibson {
962*e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev = file->private_data;
963925ca369SKent Gibson 	__poll_t events = 0;
964925ca369SKent Gibson 
965*e2b781c5SKent Gibson 	poll_wait(file, &cdev->wait, pollt);
966925ca369SKent Gibson 
967*e2b781c5SKent Gibson 	if (!kfifo_is_empty_spinlocked_noirqsave(&cdev->events,
968*e2b781c5SKent Gibson 						 &cdev->wait.lock))
969925ca369SKent Gibson 		events = EPOLLIN | EPOLLRDNORM;
970925ca369SKent Gibson 
971925ca369SKent Gibson 	return events;
972925ca369SKent Gibson }
973925ca369SKent Gibson 
97449bc5279SKent Gibson static ssize_t lineinfo_watch_read(struct file *file, char __user *buf,
975925ca369SKent Gibson 				   size_t count, loff_t *off)
976925ca369SKent Gibson {
977*e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev = file->private_data;
978925ca369SKent Gibson 	struct gpioline_info_changed event;
979925ca369SKent Gibson 	ssize_t bytes_read = 0;
980925ca369SKent Gibson 	int ret;
981925ca369SKent Gibson 
982925ca369SKent Gibson 	if (count < sizeof(event))
983925ca369SKent Gibson 		return -EINVAL;
984925ca369SKent Gibson 
985925ca369SKent Gibson 	do {
986*e2b781c5SKent Gibson 		spin_lock(&cdev->wait.lock);
987*e2b781c5SKent Gibson 		if (kfifo_is_empty(&cdev->events)) {
988925ca369SKent Gibson 			if (bytes_read) {
989*e2b781c5SKent Gibson 				spin_unlock(&cdev->wait.lock);
990925ca369SKent Gibson 				return bytes_read;
991925ca369SKent Gibson 			}
992925ca369SKent Gibson 
99349bc5279SKent Gibson 			if (file->f_flags & O_NONBLOCK) {
994*e2b781c5SKent Gibson 				spin_unlock(&cdev->wait.lock);
995925ca369SKent Gibson 				return -EAGAIN;
996925ca369SKent Gibson 			}
997925ca369SKent Gibson 
998*e2b781c5SKent Gibson 			ret = wait_event_interruptible_locked(cdev->wait,
999*e2b781c5SKent Gibson 					!kfifo_is_empty(&cdev->events));
1000925ca369SKent Gibson 			if (ret) {
1001*e2b781c5SKent Gibson 				spin_unlock(&cdev->wait.lock);
1002925ca369SKent Gibson 				return ret;
1003925ca369SKent Gibson 			}
1004925ca369SKent Gibson 		}
1005925ca369SKent Gibson 
1006*e2b781c5SKent Gibson 		ret = kfifo_out(&cdev->events, &event, 1);
1007*e2b781c5SKent Gibson 		spin_unlock(&cdev->wait.lock);
1008925ca369SKent Gibson 		if (ret != 1) {
1009925ca369SKent Gibson 			ret = -EIO;
1010925ca369SKent Gibson 			break;
1011925ca369SKent Gibson 			/* We should never get here. See lineevent_read(). */
1012925ca369SKent Gibson 		}
1013925ca369SKent Gibson 
1014925ca369SKent Gibson 		if (copy_to_user(buf + bytes_read, &event, sizeof(event)))
1015925ca369SKent Gibson 			return -EFAULT;
1016925ca369SKent Gibson 		bytes_read += sizeof(event);
1017925ca369SKent Gibson 	} while (count >= bytes_read + sizeof(event));
1018925ca369SKent Gibson 
1019925ca369SKent Gibson 	return bytes_read;
1020925ca369SKent Gibson }
1021925ca369SKent Gibson 
1022925ca369SKent Gibson /**
1023925ca369SKent Gibson  * gpio_chrdev_open() - open the chardev for ioctl operations
1024925ca369SKent Gibson  * @inode: inode for this chardev
102549bc5279SKent Gibson  * @file: file struct for storing private data
1026925ca369SKent Gibson  * Returns 0 on success
1027925ca369SKent Gibson  */
102849bc5279SKent Gibson static int gpio_chrdev_open(struct inode *inode, struct file *file)
1029925ca369SKent Gibson {
1030925ca369SKent Gibson 	struct gpio_device *gdev = container_of(inode->i_cdev,
1031925ca369SKent Gibson 						struct gpio_device, chrdev);
1032*e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev;
1033925ca369SKent Gibson 	int ret = -ENOMEM;
1034925ca369SKent Gibson 
1035925ca369SKent Gibson 	/* Fail on open if the backing gpiochip is gone */
1036925ca369SKent Gibson 	if (!gdev->chip)
1037925ca369SKent Gibson 		return -ENODEV;
1038925ca369SKent Gibson 
1039*e2b781c5SKent Gibson 	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
1040*e2b781c5SKent Gibson 	if (!cdev)
1041925ca369SKent Gibson 		return -ENOMEM;
1042925ca369SKent Gibson 
1043*e2b781c5SKent Gibson 	cdev->watched_lines = bitmap_zalloc(gdev->chip->ngpio, GFP_KERNEL);
1044*e2b781c5SKent Gibson 	if (!cdev->watched_lines)
1045*e2b781c5SKent Gibson 		goto out_free_cdev;
1046925ca369SKent Gibson 
1047*e2b781c5SKent Gibson 	init_waitqueue_head(&cdev->wait);
1048*e2b781c5SKent Gibson 	INIT_KFIFO(cdev->events);
1049*e2b781c5SKent Gibson 	cdev->gdev = gdev;
1050925ca369SKent Gibson 
1051*e2b781c5SKent Gibson 	cdev->lineinfo_changed_nb.notifier_call = lineinfo_changed_notify;
10526accc376SKent Gibson 	ret = blocking_notifier_chain_register(&gdev->notifier,
1053*e2b781c5SKent Gibson 					       &cdev->lineinfo_changed_nb);
1054925ca369SKent Gibson 	if (ret)
1055925ca369SKent Gibson 		goto out_free_bitmap;
1056925ca369SKent Gibson 
1057925ca369SKent Gibson 	get_device(&gdev->dev);
1058*e2b781c5SKent Gibson 	file->private_data = cdev;
1059925ca369SKent Gibson 
106049bc5279SKent Gibson 	ret = nonseekable_open(inode, file);
1061925ca369SKent Gibson 	if (ret)
1062925ca369SKent Gibson 		goto out_unregister_notifier;
1063925ca369SKent Gibson 
1064925ca369SKent Gibson 	return ret;
1065925ca369SKent Gibson 
1066925ca369SKent Gibson out_unregister_notifier:
10676accc376SKent Gibson 	blocking_notifier_chain_unregister(&gdev->notifier,
1068*e2b781c5SKent Gibson 					   &cdev->lineinfo_changed_nb);
1069925ca369SKent Gibson out_free_bitmap:
1070*e2b781c5SKent Gibson 	bitmap_free(cdev->watched_lines);
1071*e2b781c5SKent Gibson out_free_cdev:
1072*e2b781c5SKent Gibson 	kfree(cdev);
1073925ca369SKent Gibson 	return ret;
1074925ca369SKent Gibson }
1075925ca369SKent Gibson 
1076925ca369SKent Gibson /**
1077925ca369SKent Gibson  * gpio_chrdev_release() - close chardev after ioctl operations
1078925ca369SKent Gibson  * @inode: inode for this chardev
107949bc5279SKent Gibson  * @file: file struct for storing private data
1080925ca369SKent Gibson  * Returns 0 on success
1081925ca369SKent Gibson  */
108249bc5279SKent Gibson static int gpio_chrdev_release(struct inode *inode, struct file *file)
1083925ca369SKent Gibson {
1084*e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev = file->private_data;
1085*e2b781c5SKent Gibson 	struct gpio_device *gdev = cdev->gdev;
1086925ca369SKent Gibson 
1087*e2b781c5SKent Gibson 	bitmap_free(cdev->watched_lines);
10886accc376SKent Gibson 	blocking_notifier_chain_unregister(&gdev->notifier,
1089*e2b781c5SKent Gibson 					   &cdev->lineinfo_changed_nb);
1090925ca369SKent Gibson 	put_device(&gdev->dev);
1091*e2b781c5SKent Gibson 	kfree(cdev);
1092925ca369SKent Gibson 
1093925ca369SKent Gibson 	return 0;
1094925ca369SKent Gibson }
1095925ca369SKent Gibson 
1096925ca369SKent Gibson static const struct file_operations gpio_fileops = {
1097925ca369SKent Gibson 	.release = gpio_chrdev_release,
1098925ca369SKent Gibson 	.open = gpio_chrdev_open,
1099925ca369SKent Gibson 	.poll = lineinfo_watch_poll,
1100925ca369SKent Gibson 	.read = lineinfo_watch_read,
1101925ca369SKent Gibson 	.owner = THIS_MODULE,
1102925ca369SKent Gibson 	.llseek = no_llseek,
1103925ca369SKent Gibson 	.unlocked_ioctl = gpio_ioctl,
1104925ca369SKent Gibson #ifdef CONFIG_COMPAT
1105925ca369SKent Gibson 	.compat_ioctl = gpio_ioctl_compat,
1106925ca369SKent Gibson #endif
1107925ca369SKent Gibson };
1108925ca369SKent Gibson 
1109925ca369SKent Gibson int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt)
1110925ca369SKent Gibson {
1111925ca369SKent Gibson 	int ret;
1112925ca369SKent Gibson 
1113925ca369SKent Gibson 	cdev_init(&gdev->chrdev, &gpio_fileops);
1114925ca369SKent Gibson 	gdev->chrdev.owner = THIS_MODULE;
1115925ca369SKent Gibson 	gdev->dev.devt = MKDEV(MAJOR(devt), gdev->id);
1116925ca369SKent Gibson 
1117925ca369SKent Gibson 	ret = cdev_device_add(&gdev->chrdev, &gdev->dev);
1118925ca369SKent Gibson 	if (ret)
1119925ca369SKent Gibson 		return ret;
1120925ca369SKent Gibson 
1121925ca369SKent Gibson 	chip_dbg(gdev->chip, "added GPIO chardev (%d:%d)\n",
1122925ca369SKent Gibson 		 MAJOR(devt), gdev->id);
1123925ca369SKent Gibson 
1124925ca369SKent Gibson 	return 0;
1125925ca369SKent Gibson }
1126925ca369SKent Gibson 
1127925ca369SKent Gibson void gpiolib_cdev_unregister(struct gpio_device *gdev)
1128925ca369SKent Gibson {
1129925ca369SKent Gibson 	cdev_device_del(&gdev->chrdev, &gdev->dev);
1130925ca369SKent Gibson }
1131