xref: /openbmc/linux/drivers/gpio/gpiolib-cdev.c (revision 49bc52798d7bb66e958d7ea7378c38ec258b9037)
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
42925ca369SKent Gibson  * @numdescs: 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];
48925ca369SKent Gibson 	u32 numdescs;
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 
141925ca369SKent Gibson 	for (i = 0; i < lh->numdescs; 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 
161925ca369SKent Gibson 		atomic_notifier_call_chain(&desc->gdev->notifier,
162925ca369SKent Gibson 					   GPIOLINE_CHANGED_CONFIG, desc);
163925ca369SKent Gibson 	}
164925ca369SKent Gibson 	return 0;
165925ca369SKent Gibson }
166925ca369SKent Gibson 
167*49bc5279SKent Gibson static long linehandle_ioctl(struct file *file, unsigned int cmd,
168925ca369SKent Gibson 			     unsigned long arg)
169925ca369SKent Gibson {
170*49bc5279SKent 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,
180925ca369SKent Gibson 							lh->numdescs,
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));
188925ca369SKent Gibson 		for (i = 0; i < lh->numdescs; 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] */
207925ca369SKent Gibson 		for (i = 0; i < lh->numdescs; 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,
213925ca369SKent Gibson 						     lh->numdescs,
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
224*49bc5279SKent Gibson static long linehandle_ioctl_compat(struct file *file, unsigned int cmd,
225925ca369SKent Gibson 				    unsigned long arg)
226925ca369SKent Gibson {
227*49bc5279SKent Gibson 	return linehandle_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
228925ca369SKent Gibson }
229925ca369SKent Gibson #endif
230925ca369SKent Gibson 
231*49bc5279SKent Gibson static int linehandle_release(struct inode *inode, struct file *file)
232925ca369SKent Gibson {
233*49bc5279SKent Gibson 	struct linehandle_state *lh = file->private_data;
234925ca369SKent Gibson 	struct gpio_device *gdev = lh->gdev;
235925ca369SKent Gibson 	int i;
236925ca369SKent Gibson 
237925ca369SKent Gibson 	for (i = 0; i < lh->numdescs; 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 
328925ca369SKent Gibson 		atomic_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 	}
334925ca369SKent Gibson 	/* Let i point at the last handle */
335925ca369SKent Gibson 	i--;
336925ca369SKent Gibson 	lh->numdescs = handlereq.lines;
337925ca369SKent Gibson 
338925ca369SKent Gibson 	fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
339925ca369SKent Gibson 	if (fd < 0) {
340925ca369SKent Gibson 		ret = fd;
341925ca369SKent Gibson 		goto out_free_descs;
342925ca369SKent Gibson 	}
343925ca369SKent Gibson 
344925ca369SKent Gibson 	file = anon_inode_getfile("gpio-linehandle",
345925ca369SKent Gibson 				  &linehandle_fileops,
346925ca369SKent Gibson 				  lh,
347925ca369SKent Gibson 				  O_RDONLY | O_CLOEXEC);
348925ca369SKent Gibson 	if (IS_ERR(file)) {
349925ca369SKent Gibson 		ret = PTR_ERR(file);
350925ca369SKent Gibson 		goto out_put_unused_fd;
351925ca369SKent Gibson 	}
352925ca369SKent Gibson 
353925ca369SKent Gibson 	handlereq.fd = fd;
354925ca369SKent Gibson 	if (copy_to_user(ip, &handlereq, sizeof(handlereq))) {
355925ca369SKent Gibson 		/*
356925ca369SKent Gibson 		 * fput() will trigger the release() callback, so do not go onto
357925ca369SKent Gibson 		 * the regular error cleanup path here.
358925ca369SKent Gibson 		 */
359925ca369SKent Gibson 		fput(file);
360925ca369SKent Gibson 		put_unused_fd(fd);
361925ca369SKent Gibson 		return -EFAULT;
362925ca369SKent Gibson 	}
363925ca369SKent Gibson 
364925ca369SKent Gibson 	fd_install(fd, file);
365925ca369SKent Gibson 
366925ca369SKent Gibson 	dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n",
367925ca369SKent Gibson 		lh->numdescs);
368925ca369SKent Gibson 
369925ca369SKent Gibson 	return 0;
370925ca369SKent Gibson 
371925ca369SKent Gibson out_put_unused_fd:
372925ca369SKent Gibson 	put_unused_fd(fd);
373925ca369SKent Gibson out_free_descs:
374925ca369SKent Gibson 	for (i = 0; i < count; i++)
375925ca369SKent Gibson 		gpiod_free(lh->descs[i]);
376925ca369SKent Gibson 	kfree(lh->label);
377925ca369SKent Gibson out_free_lh:
378925ca369SKent Gibson 	kfree(lh);
379925ca369SKent Gibson 	put_device(&gdev->dev);
380925ca369SKent Gibson 	return ret;
381925ca369SKent Gibson }
382925ca369SKent Gibson 
383925ca369SKent Gibson /*
384925ca369SKent Gibson  * GPIO line event management
385925ca369SKent Gibson  */
386925ca369SKent Gibson 
387925ca369SKent Gibson /**
388925ca369SKent Gibson  * struct lineevent_state - contains the state of a userspace event
389925ca369SKent Gibson  * @gdev: the GPIO device the event pertains to
390925ca369SKent Gibson  * @label: consumer label used to tag descriptors
391925ca369SKent Gibson  * @desc: the GPIO descriptor held by this event
392925ca369SKent Gibson  * @eflags: the event flags this line was requested with
393925ca369SKent Gibson  * @irq: the interrupt that trigger in response to events on this GPIO
394925ca369SKent Gibson  * @wait: wait queue that handles blocking reads of events
395925ca369SKent Gibson  * @events: KFIFO for the GPIO events
396925ca369SKent Gibson  * @timestamp: cache for the timestamp storing it between hardirq
397925ca369SKent Gibson  * and IRQ thread, used to bring the timestamp close to the actual
398925ca369SKent Gibson  * event
399925ca369SKent Gibson  */
400925ca369SKent Gibson struct lineevent_state {
401925ca369SKent Gibson 	struct gpio_device *gdev;
402925ca369SKent Gibson 	const char *label;
403925ca369SKent Gibson 	struct gpio_desc *desc;
404925ca369SKent Gibson 	u32 eflags;
405925ca369SKent Gibson 	int irq;
406925ca369SKent Gibson 	wait_queue_head_t wait;
407925ca369SKent Gibson 	DECLARE_KFIFO(events, struct gpioevent_data, 16);
408925ca369SKent Gibson 	u64 timestamp;
409925ca369SKent Gibson };
410925ca369SKent Gibson 
411925ca369SKent Gibson #define GPIOEVENT_REQUEST_VALID_FLAGS \
412925ca369SKent Gibson 	(GPIOEVENT_REQUEST_RISING_EDGE | \
413925ca369SKent Gibson 	GPIOEVENT_REQUEST_FALLING_EDGE)
414925ca369SKent Gibson 
415*49bc5279SKent Gibson static __poll_t lineevent_poll(struct file *file,
416925ca369SKent Gibson 			       struct poll_table_struct *wait)
417925ca369SKent Gibson {
418*49bc5279SKent Gibson 	struct lineevent_state *le = file->private_data;
419925ca369SKent Gibson 	__poll_t events = 0;
420925ca369SKent Gibson 
421*49bc5279SKent Gibson 	poll_wait(file, &le->wait, wait);
422925ca369SKent Gibson 
423925ca369SKent Gibson 	if (!kfifo_is_empty_spinlocked_noirqsave(&le->events, &le->wait.lock))
424925ca369SKent Gibson 		events = EPOLLIN | EPOLLRDNORM;
425925ca369SKent Gibson 
426925ca369SKent Gibson 	return events;
427925ca369SKent Gibson }
428925ca369SKent Gibson 
429925ca369SKent Gibson 
430*49bc5279SKent Gibson static ssize_t lineevent_read(struct file *file,
431925ca369SKent Gibson 			      char __user *buf,
432925ca369SKent Gibson 			      size_t count,
433925ca369SKent Gibson 			      loff_t *f_ps)
434925ca369SKent Gibson {
435*49bc5279SKent Gibson 	struct lineevent_state *le = file->private_data;
436925ca369SKent Gibson 	struct gpioevent_data ge;
437925ca369SKent Gibson 	ssize_t bytes_read = 0;
438925ca369SKent Gibson 	int ret;
439925ca369SKent Gibson 
440925ca369SKent Gibson 	if (count < sizeof(ge))
441925ca369SKent Gibson 		return -EINVAL;
442925ca369SKent Gibson 
443925ca369SKent Gibson 	do {
444925ca369SKent Gibson 		spin_lock(&le->wait.lock);
445925ca369SKent Gibson 		if (kfifo_is_empty(&le->events)) {
446925ca369SKent Gibson 			if (bytes_read) {
447925ca369SKent Gibson 				spin_unlock(&le->wait.lock);
448925ca369SKent Gibson 				return bytes_read;
449925ca369SKent Gibson 			}
450925ca369SKent Gibson 
451*49bc5279SKent Gibson 			if (file->f_flags & O_NONBLOCK) {
452925ca369SKent Gibson 				spin_unlock(&le->wait.lock);
453925ca369SKent Gibson 				return -EAGAIN;
454925ca369SKent Gibson 			}
455925ca369SKent Gibson 
456925ca369SKent Gibson 			ret = wait_event_interruptible_locked(le->wait,
457925ca369SKent Gibson 					!kfifo_is_empty(&le->events));
458925ca369SKent Gibson 			if (ret) {
459925ca369SKent Gibson 				spin_unlock(&le->wait.lock);
460925ca369SKent Gibson 				return ret;
461925ca369SKent Gibson 			}
462925ca369SKent Gibson 		}
463925ca369SKent Gibson 
464925ca369SKent Gibson 		ret = kfifo_out(&le->events, &ge, 1);
465925ca369SKent Gibson 		spin_unlock(&le->wait.lock);
466925ca369SKent Gibson 		if (ret != 1) {
467925ca369SKent Gibson 			/*
468925ca369SKent Gibson 			 * This should never happen - we were holding the lock
469925ca369SKent Gibson 			 * from the moment we learned the fifo is no longer
470925ca369SKent Gibson 			 * empty until now.
471925ca369SKent Gibson 			 */
472925ca369SKent Gibson 			ret = -EIO;
473925ca369SKent Gibson 			break;
474925ca369SKent Gibson 		}
475925ca369SKent Gibson 
476925ca369SKent Gibson 		if (copy_to_user(buf + bytes_read, &ge, sizeof(ge)))
477925ca369SKent Gibson 			return -EFAULT;
478925ca369SKent Gibson 		bytes_read += sizeof(ge);
479925ca369SKent Gibson 	} while (count >= bytes_read + sizeof(ge));
480925ca369SKent Gibson 
481925ca369SKent Gibson 	return bytes_read;
482925ca369SKent Gibson }
483925ca369SKent Gibson 
484*49bc5279SKent Gibson static int lineevent_release(struct inode *inode, struct file *file)
485925ca369SKent Gibson {
486*49bc5279SKent Gibson 	struct lineevent_state *le = file->private_data;
487925ca369SKent Gibson 	struct gpio_device *gdev = le->gdev;
488925ca369SKent Gibson 
489925ca369SKent Gibson 	free_irq(le->irq, le);
490925ca369SKent Gibson 	gpiod_free(le->desc);
491925ca369SKent Gibson 	kfree(le->label);
492925ca369SKent Gibson 	kfree(le);
493925ca369SKent Gibson 	put_device(&gdev->dev);
494925ca369SKent Gibson 	return 0;
495925ca369SKent Gibson }
496925ca369SKent Gibson 
497*49bc5279SKent Gibson static long lineevent_ioctl(struct file *file, unsigned int cmd,
498925ca369SKent Gibson 			    unsigned long arg)
499925ca369SKent Gibson {
500*49bc5279SKent Gibson 	struct lineevent_state *le = file->private_data;
501925ca369SKent Gibson 	void __user *ip = (void __user *)arg;
502925ca369SKent Gibson 	struct gpiohandle_data ghd;
503925ca369SKent Gibson 
504925ca369SKent Gibson 	/*
505925ca369SKent Gibson 	 * We can get the value for an event line but not set it,
506925ca369SKent Gibson 	 * because it is input by definition.
507925ca369SKent Gibson 	 */
508925ca369SKent Gibson 	if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) {
509925ca369SKent Gibson 		int val;
510925ca369SKent Gibson 
511925ca369SKent Gibson 		memset(&ghd, 0, sizeof(ghd));
512925ca369SKent Gibson 
513925ca369SKent Gibson 		val = gpiod_get_value_cansleep(le->desc);
514925ca369SKent Gibson 		if (val < 0)
515925ca369SKent Gibson 			return val;
516925ca369SKent Gibson 		ghd.values[0] = val;
517925ca369SKent Gibson 
518925ca369SKent Gibson 		if (copy_to_user(ip, &ghd, sizeof(ghd)))
519925ca369SKent Gibson 			return -EFAULT;
520925ca369SKent Gibson 
521925ca369SKent Gibson 		return 0;
522925ca369SKent Gibson 	}
523925ca369SKent Gibson 	return -EINVAL;
524925ca369SKent Gibson }
525925ca369SKent Gibson 
526925ca369SKent Gibson #ifdef CONFIG_COMPAT
527*49bc5279SKent Gibson static long lineevent_ioctl_compat(struct file *file, unsigned int cmd,
528925ca369SKent Gibson 				   unsigned long arg)
529925ca369SKent Gibson {
530*49bc5279SKent Gibson 	return lineevent_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
531925ca369SKent Gibson }
532925ca369SKent Gibson #endif
533925ca369SKent Gibson 
534925ca369SKent Gibson static const struct file_operations lineevent_fileops = {
535925ca369SKent Gibson 	.release = lineevent_release,
536925ca369SKent Gibson 	.read = lineevent_read,
537925ca369SKent Gibson 	.poll = lineevent_poll,
538925ca369SKent Gibson 	.owner = THIS_MODULE,
539925ca369SKent Gibson 	.llseek = noop_llseek,
540925ca369SKent Gibson 	.unlocked_ioctl = lineevent_ioctl,
541925ca369SKent Gibson #ifdef CONFIG_COMPAT
542925ca369SKent Gibson 	.compat_ioctl = lineevent_ioctl_compat,
543925ca369SKent Gibson #endif
544925ca369SKent Gibson };
545925ca369SKent Gibson 
546925ca369SKent Gibson static irqreturn_t lineevent_irq_thread(int irq, void *p)
547925ca369SKent Gibson {
548925ca369SKent Gibson 	struct lineevent_state *le = p;
549925ca369SKent Gibson 	struct gpioevent_data ge;
550925ca369SKent Gibson 	int ret;
551925ca369SKent Gibson 
552925ca369SKent Gibson 	/* Do not leak kernel stack to userspace */
553925ca369SKent Gibson 	memset(&ge, 0, sizeof(ge));
554925ca369SKent Gibson 
555925ca369SKent Gibson 	/*
556925ca369SKent Gibson 	 * We may be running from a nested threaded interrupt in which case
557925ca369SKent Gibson 	 * we didn't get the timestamp from lineevent_irq_handler().
558925ca369SKent Gibson 	 */
559925ca369SKent Gibson 	if (!le->timestamp)
560925ca369SKent Gibson 		ge.timestamp = ktime_get_ns();
561925ca369SKent Gibson 	else
562925ca369SKent Gibson 		ge.timestamp = le->timestamp;
563925ca369SKent Gibson 
564925ca369SKent Gibson 	if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE
565925ca369SKent Gibson 	    && le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
566925ca369SKent Gibson 		int level = gpiod_get_value_cansleep(le->desc);
567925ca369SKent Gibson 
568925ca369SKent Gibson 		if (level)
569925ca369SKent Gibson 			/* Emit low-to-high event */
570925ca369SKent Gibson 			ge.id = GPIOEVENT_EVENT_RISING_EDGE;
571925ca369SKent Gibson 		else
572925ca369SKent Gibson 			/* Emit high-to-low event */
573925ca369SKent Gibson 			ge.id = GPIOEVENT_EVENT_FALLING_EDGE;
574925ca369SKent Gibson 	} else if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE) {
575925ca369SKent Gibson 		/* Emit low-to-high event */
576925ca369SKent Gibson 		ge.id = GPIOEVENT_EVENT_RISING_EDGE;
577925ca369SKent Gibson 	} else if (le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
578925ca369SKent Gibson 		/* Emit high-to-low event */
579925ca369SKent Gibson 		ge.id = GPIOEVENT_EVENT_FALLING_EDGE;
580925ca369SKent Gibson 	} else {
581925ca369SKent Gibson 		return IRQ_NONE;
582925ca369SKent Gibson 	}
583925ca369SKent Gibson 
584925ca369SKent Gibson 	ret = kfifo_in_spinlocked_noirqsave(&le->events, &ge,
585925ca369SKent Gibson 					    1, &le->wait.lock);
586925ca369SKent Gibson 	if (ret)
587925ca369SKent Gibson 		wake_up_poll(&le->wait, EPOLLIN);
588925ca369SKent Gibson 	else
589925ca369SKent Gibson 		pr_debug_ratelimited("event FIFO is full - event dropped\n");
590925ca369SKent Gibson 
591925ca369SKent Gibson 	return IRQ_HANDLED;
592925ca369SKent Gibson }
593925ca369SKent Gibson 
594925ca369SKent Gibson static irqreturn_t lineevent_irq_handler(int irq, void *p)
595925ca369SKent Gibson {
596925ca369SKent Gibson 	struct lineevent_state *le = p;
597925ca369SKent Gibson 
598925ca369SKent Gibson 	/*
599925ca369SKent Gibson 	 * Just store the timestamp in hardirq context so we get it as
600925ca369SKent Gibson 	 * close in time as possible to the actual event.
601925ca369SKent Gibson 	 */
602925ca369SKent Gibson 	le->timestamp = ktime_get_ns();
603925ca369SKent Gibson 
604925ca369SKent Gibson 	return IRQ_WAKE_THREAD;
605925ca369SKent Gibson }
606925ca369SKent Gibson 
607925ca369SKent Gibson static int lineevent_create(struct gpio_device *gdev, void __user *ip)
608925ca369SKent Gibson {
609925ca369SKent Gibson 	struct gpioevent_request eventreq;
610925ca369SKent Gibson 	struct lineevent_state *le;
611925ca369SKent Gibson 	struct gpio_desc *desc;
612925ca369SKent Gibson 	struct file *file;
613925ca369SKent Gibson 	u32 offset;
614925ca369SKent Gibson 	u32 lflags;
615925ca369SKent Gibson 	u32 eflags;
616925ca369SKent Gibson 	int fd;
617925ca369SKent Gibson 	int ret;
618925ca369SKent Gibson 	int irqflags = 0;
619925ca369SKent Gibson 
620925ca369SKent Gibson 	if (copy_from_user(&eventreq, ip, sizeof(eventreq)))
621925ca369SKent Gibson 		return -EFAULT;
622925ca369SKent Gibson 
623925ca369SKent Gibson 	offset = eventreq.lineoffset;
624925ca369SKent Gibson 	lflags = eventreq.handleflags;
625925ca369SKent Gibson 	eflags = eventreq.eventflags;
626925ca369SKent Gibson 
627925ca369SKent Gibson 	desc = gpiochip_get_desc(gdev->chip, offset);
628925ca369SKent Gibson 	if (IS_ERR(desc))
629925ca369SKent Gibson 		return PTR_ERR(desc);
630925ca369SKent Gibson 
631925ca369SKent Gibson 	/* Return an error if a unknown flag is set */
632925ca369SKent Gibson 	if ((lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS) ||
633925ca369SKent Gibson 	    (eflags & ~GPIOEVENT_REQUEST_VALID_FLAGS))
634925ca369SKent Gibson 		return -EINVAL;
635925ca369SKent Gibson 
636925ca369SKent Gibson 	/* This is just wrong: we don't look for events on output lines */
637925ca369SKent Gibson 	if ((lflags & GPIOHANDLE_REQUEST_OUTPUT) ||
638925ca369SKent Gibson 	    (lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN) ||
639925ca369SKent Gibson 	    (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE))
640925ca369SKent Gibson 		return -EINVAL;
641925ca369SKent Gibson 
642925ca369SKent Gibson 	/* Only one bias flag can be set. */
643925ca369SKent Gibson 	if (((lflags & GPIOHANDLE_REQUEST_BIAS_DISABLE) &&
644925ca369SKent Gibson 	     (lflags & (GPIOHANDLE_REQUEST_BIAS_PULL_DOWN |
645925ca369SKent Gibson 			GPIOHANDLE_REQUEST_BIAS_PULL_UP))) ||
646925ca369SKent Gibson 	    ((lflags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN) &&
647925ca369SKent Gibson 	     (lflags & GPIOHANDLE_REQUEST_BIAS_PULL_UP)))
648925ca369SKent Gibson 		return -EINVAL;
649925ca369SKent Gibson 
650925ca369SKent Gibson 	le = kzalloc(sizeof(*le), GFP_KERNEL);
651925ca369SKent Gibson 	if (!le)
652925ca369SKent Gibson 		return -ENOMEM;
653925ca369SKent Gibson 	le->gdev = gdev;
654925ca369SKent Gibson 	get_device(&gdev->dev);
655925ca369SKent Gibson 
656925ca369SKent Gibson 	/* Make sure this is terminated */
657925ca369SKent Gibson 	eventreq.consumer_label[sizeof(eventreq.consumer_label)-1] = '\0';
658925ca369SKent Gibson 	if (strlen(eventreq.consumer_label)) {
659925ca369SKent Gibson 		le->label = kstrdup(eventreq.consumer_label,
660925ca369SKent Gibson 				    GFP_KERNEL);
661925ca369SKent Gibson 		if (!le->label) {
662925ca369SKent Gibson 			ret = -ENOMEM;
663925ca369SKent Gibson 			goto out_free_le;
664925ca369SKent Gibson 		}
665925ca369SKent Gibson 	}
666925ca369SKent Gibson 
667925ca369SKent Gibson 	ret = gpiod_request(desc, le->label);
668925ca369SKent Gibson 	if (ret)
669925ca369SKent Gibson 		goto out_free_label;
670925ca369SKent Gibson 	le->desc = desc;
671925ca369SKent Gibson 	le->eflags = eflags;
672925ca369SKent Gibson 
673c274b58aSKent Gibson 	linehandle_flags_to_desc_flags(lflags, &desc->flags);
674925ca369SKent Gibson 
675925ca369SKent Gibson 	ret = gpiod_direction_input(desc);
676925ca369SKent Gibson 	if (ret)
677925ca369SKent Gibson 		goto out_free_desc;
678925ca369SKent Gibson 
679925ca369SKent Gibson 	atomic_notifier_call_chain(&desc->gdev->notifier,
680925ca369SKent Gibson 				   GPIOLINE_CHANGED_REQUESTED, desc);
681925ca369SKent Gibson 
682925ca369SKent Gibson 	le->irq = gpiod_to_irq(desc);
683925ca369SKent Gibson 	if (le->irq <= 0) {
684925ca369SKent Gibson 		ret = -ENODEV;
685925ca369SKent Gibson 		goto out_free_desc;
686925ca369SKent Gibson 	}
687925ca369SKent Gibson 
688925ca369SKent Gibson 	if (eflags & GPIOEVENT_REQUEST_RISING_EDGE)
689925ca369SKent Gibson 		irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
690925ca369SKent Gibson 			IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
691925ca369SKent Gibson 	if (eflags & GPIOEVENT_REQUEST_FALLING_EDGE)
692925ca369SKent Gibson 		irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
693925ca369SKent Gibson 			IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
694925ca369SKent Gibson 	irqflags |= IRQF_ONESHOT;
695925ca369SKent Gibson 
696925ca369SKent Gibson 	INIT_KFIFO(le->events);
697925ca369SKent Gibson 	init_waitqueue_head(&le->wait);
698925ca369SKent Gibson 
699925ca369SKent Gibson 	/* Request a thread to read the events */
700925ca369SKent Gibson 	ret = request_threaded_irq(le->irq,
701925ca369SKent Gibson 				   lineevent_irq_handler,
702925ca369SKent Gibson 				   lineevent_irq_thread,
703925ca369SKent Gibson 				   irqflags,
704925ca369SKent Gibson 				   le->label,
705925ca369SKent Gibson 				   le);
706925ca369SKent Gibson 	if (ret)
707925ca369SKent Gibson 		goto out_free_desc;
708925ca369SKent Gibson 
709925ca369SKent Gibson 	fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
710925ca369SKent Gibson 	if (fd < 0) {
711925ca369SKent Gibson 		ret = fd;
712925ca369SKent Gibson 		goto out_free_irq;
713925ca369SKent Gibson 	}
714925ca369SKent Gibson 
715925ca369SKent Gibson 	file = anon_inode_getfile("gpio-event",
716925ca369SKent Gibson 				  &lineevent_fileops,
717925ca369SKent Gibson 				  le,
718925ca369SKent Gibson 				  O_RDONLY | O_CLOEXEC);
719925ca369SKent Gibson 	if (IS_ERR(file)) {
720925ca369SKent Gibson 		ret = PTR_ERR(file);
721925ca369SKent Gibson 		goto out_put_unused_fd;
722925ca369SKent Gibson 	}
723925ca369SKent Gibson 
724925ca369SKent Gibson 	eventreq.fd = fd;
725925ca369SKent Gibson 	if (copy_to_user(ip, &eventreq, sizeof(eventreq))) {
726925ca369SKent Gibson 		/*
727925ca369SKent Gibson 		 * fput() will trigger the release() callback, so do not go onto
728925ca369SKent Gibson 		 * the regular error cleanup path here.
729925ca369SKent Gibson 		 */
730925ca369SKent Gibson 		fput(file);
731925ca369SKent Gibson 		put_unused_fd(fd);
732925ca369SKent Gibson 		return -EFAULT;
733925ca369SKent Gibson 	}
734925ca369SKent Gibson 
735925ca369SKent Gibson 	fd_install(fd, file);
736925ca369SKent Gibson 
737925ca369SKent Gibson 	return 0;
738925ca369SKent Gibson 
739925ca369SKent Gibson out_put_unused_fd:
740925ca369SKent Gibson 	put_unused_fd(fd);
741925ca369SKent Gibson out_free_irq:
742925ca369SKent Gibson 	free_irq(le->irq, le);
743925ca369SKent Gibson out_free_desc:
744925ca369SKent Gibson 	gpiod_free(le->desc);
745925ca369SKent Gibson out_free_label:
746925ca369SKent Gibson 	kfree(le->label);
747925ca369SKent Gibson out_free_le:
748925ca369SKent Gibson 	kfree(le);
749925ca369SKent Gibson 	put_device(&gdev->dev);
750925ca369SKent Gibson 	return ret;
751925ca369SKent Gibson }
752925ca369SKent Gibson 
753925ca369SKent Gibson static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
754925ca369SKent Gibson 				  struct gpioline_info *info)
755925ca369SKent Gibson {
756925ca369SKent Gibson 	struct gpio_chip *gc = desc->gdev->chip;
757925ca369SKent Gibson 	bool ok_for_pinctrl;
758925ca369SKent Gibson 	unsigned long flags;
759925ca369SKent Gibson 
760925ca369SKent Gibson 	/*
761925ca369SKent Gibson 	 * This function takes a mutex so we must check this before taking
762925ca369SKent Gibson 	 * the spinlock.
763925ca369SKent Gibson 	 *
764925ca369SKent Gibson 	 * FIXME: find a non-racy way to retrieve this information. Maybe a
765925ca369SKent Gibson 	 * lock common to both frameworks?
766925ca369SKent Gibson 	 */
767925ca369SKent Gibson 	ok_for_pinctrl =
768925ca369SKent Gibson 		pinctrl_gpio_can_use_line(gc->base + info->line_offset);
769925ca369SKent Gibson 
770925ca369SKent Gibson 	spin_lock_irqsave(&gpio_lock, flags);
771925ca369SKent Gibson 
772925ca369SKent Gibson 	if (desc->name) {
773925ca369SKent Gibson 		strncpy(info->name, desc->name, sizeof(info->name));
774925ca369SKent Gibson 		info->name[sizeof(info->name) - 1] = '\0';
775925ca369SKent Gibson 	} else {
776925ca369SKent Gibson 		info->name[0] = '\0';
777925ca369SKent Gibson 	}
778925ca369SKent Gibson 
779925ca369SKent Gibson 	if (desc->label) {
780925ca369SKent Gibson 		strncpy(info->consumer, desc->label, sizeof(info->consumer));
781925ca369SKent Gibson 		info->consumer[sizeof(info->consumer) - 1] = '\0';
782925ca369SKent Gibson 	} else {
783925ca369SKent Gibson 		info->consumer[0] = '\0';
784925ca369SKent Gibson 	}
785925ca369SKent Gibson 
786925ca369SKent Gibson 	/*
787925ca369SKent Gibson 	 * Userspace only need to know that the kernel is using this GPIO so
788925ca369SKent Gibson 	 * it can't use it.
789925ca369SKent Gibson 	 */
790925ca369SKent Gibson 	info->flags = 0;
791925ca369SKent Gibson 	if (test_bit(FLAG_REQUESTED, &desc->flags) ||
792925ca369SKent Gibson 	    test_bit(FLAG_IS_HOGGED, &desc->flags) ||
793925ca369SKent Gibson 	    test_bit(FLAG_USED_AS_IRQ, &desc->flags) ||
794925ca369SKent Gibson 	    test_bit(FLAG_EXPORT, &desc->flags) ||
795925ca369SKent Gibson 	    test_bit(FLAG_SYSFS, &desc->flags) ||
796925ca369SKent Gibson 	    !ok_for_pinctrl)
797925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_KERNEL;
798925ca369SKent Gibson 	if (test_bit(FLAG_IS_OUT, &desc->flags))
799925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_IS_OUT;
800925ca369SKent Gibson 	if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
801925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_ACTIVE_LOW;
802925ca369SKent Gibson 	if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))
803925ca369SKent Gibson 		info->flags |= (GPIOLINE_FLAG_OPEN_DRAIN |
804925ca369SKent Gibson 				GPIOLINE_FLAG_IS_OUT);
805925ca369SKent Gibson 	if (test_bit(FLAG_OPEN_SOURCE, &desc->flags))
806925ca369SKent Gibson 		info->flags |= (GPIOLINE_FLAG_OPEN_SOURCE |
807925ca369SKent Gibson 				GPIOLINE_FLAG_IS_OUT);
808925ca369SKent Gibson 	if (test_bit(FLAG_BIAS_DISABLE, &desc->flags))
809925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_BIAS_DISABLE;
810925ca369SKent Gibson 	if (test_bit(FLAG_PULL_DOWN, &desc->flags))
811925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_BIAS_PULL_DOWN;
812925ca369SKent Gibson 	if (test_bit(FLAG_PULL_UP, &desc->flags))
813925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_BIAS_PULL_UP;
814925ca369SKent Gibson 
815925ca369SKent Gibson 	spin_unlock_irqrestore(&gpio_lock, flags);
816925ca369SKent Gibson }
817925ca369SKent Gibson 
818925ca369SKent Gibson struct gpio_chardev_data {
819925ca369SKent Gibson 	struct gpio_device *gdev;
820925ca369SKent Gibson 	wait_queue_head_t wait;
821925ca369SKent Gibson 	DECLARE_KFIFO(events, struct gpioline_info_changed, 32);
822925ca369SKent Gibson 	struct notifier_block lineinfo_changed_nb;
823925ca369SKent Gibson 	unsigned long *watched_lines;
824925ca369SKent Gibson };
825925ca369SKent Gibson 
826925ca369SKent Gibson /*
827925ca369SKent Gibson  * gpio_ioctl() - ioctl handler for the GPIO chardev
828925ca369SKent Gibson  */
829*49bc5279SKent Gibson static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
830925ca369SKent Gibson {
831*49bc5279SKent Gibson 	struct gpio_chardev_data *priv = file->private_data;
832925ca369SKent Gibson 	struct gpio_device *gdev = priv->gdev;
833925ca369SKent Gibson 	struct gpio_chip *gc = gdev->chip;
834925ca369SKent Gibson 	void __user *ip = (void __user *)arg;
835925ca369SKent Gibson 	struct gpio_desc *desc;
836925ca369SKent Gibson 	__u32 offset;
837925ca369SKent Gibson 	int hwgpio;
838925ca369SKent Gibson 
839925ca369SKent Gibson 	/* We fail any subsequent ioctl():s when the chip is gone */
840925ca369SKent Gibson 	if (!gc)
841925ca369SKent Gibson 		return -ENODEV;
842925ca369SKent Gibson 
843925ca369SKent Gibson 	/* Fill in the struct and pass to userspace */
844925ca369SKent Gibson 	if (cmd == GPIO_GET_CHIPINFO_IOCTL) {
845925ca369SKent Gibson 		struct gpiochip_info chipinfo;
846925ca369SKent Gibson 
847925ca369SKent Gibson 		memset(&chipinfo, 0, sizeof(chipinfo));
848925ca369SKent Gibson 
849925ca369SKent Gibson 		strncpy(chipinfo.name, dev_name(&gdev->dev),
850925ca369SKent Gibson 			sizeof(chipinfo.name));
851925ca369SKent Gibson 		chipinfo.name[sizeof(chipinfo.name)-1] = '\0';
852925ca369SKent Gibson 		strncpy(chipinfo.label, gdev->label,
853925ca369SKent Gibson 			sizeof(chipinfo.label));
854925ca369SKent Gibson 		chipinfo.label[sizeof(chipinfo.label)-1] = '\0';
855925ca369SKent Gibson 		chipinfo.lines = gdev->ngpio;
856925ca369SKent Gibson 		if (copy_to_user(ip, &chipinfo, sizeof(chipinfo)))
857925ca369SKent Gibson 			return -EFAULT;
858925ca369SKent Gibson 		return 0;
859925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEINFO_IOCTL) {
860925ca369SKent Gibson 		struct gpioline_info lineinfo;
861925ca369SKent Gibson 
862925ca369SKent Gibson 		if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
863925ca369SKent Gibson 			return -EFAULT;
864925ca369SKent Gibson 
865925ca369SKent Gibson 		desc = gpiochip_get_desc(gc, lineinfo.line_offset);
866925ca369SKent Gibson 		if (IS_ERR(desc))
867925ca369SKent Gibson 			return PTR_ERR(desc);
868925ca369SKent Gibson 
869925ca369SKent Gibson 		hwgpio = gpio_chip_hwgpio(desc);
870925ca369SKent Gibson 
871925ca369SKent Gibson 		gpio_desc_to_lineinfo(desc, &lineinfo);
872925ca369SKent Gibson 
873925ca369SKent Gibson 		if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
874925ca369SKent Gibson 			return -EFAULT;
875925ca369SKent Gibson 		return 0;
876925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) {
877925ca369SKent Gibson 		return linehandle_create(gdev, ip);
878925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEEVENT_IOCTL) {
879925ca369SKent Gibson 		return lineevent_create(gdev, ip);
880925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) {
881925ca369SKent Gibson 		struct gpioline_info lineinfo;
882925ca369SKent Gibson 
883925ca369SKent Gibson 		if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
884925ca369SKent Gibson 			return -EFAULT;
885925ca369SKent Gibson 
886925ca369SKent Gibson 		desc = gpiochip_get_desc(gc, lineinfo.line_offset);
887925ca369SKent Gibson 		if (IS_ERR(desc))
888925ca369SKent Gibson 			return PTR_ERR(desc);
889925ca369SKent Gibson 
890925ca369SKent Gibson 		hwgpio = gpio_chip_hwgpio(desc);
891925ca369SKent Gibson 
892925ca369SKent Gibson 		if (test_bit(hwgpio, priv->watched_lines))
893925ca369SKent Gibson 			return -EBUSY;
894925ca369SKent Gibson 
895925ca369SKent Gibson 		gpio_desc_to_lineinfo(desc, &lineinfo);
896925ca369SKent Gibson 
897925ca369SKent Gibson 		if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
898925ca369SKent Gibson 			return -EFAULT;
899925ca369SKent Gibson 
900925ca369SKent Gibson 		set_bit(hwgpio, priv->watched_lines);
901925ca369SKent Gibson 		return 0;
902925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEINFO_UNWATCH_IOCTL) {
903925ca369SKent Gibson 		if (copy_from_user(&offset, ip, sizeof(offset)))
904925ca369SKent Gibson 			return -EFAULT;
905925ca369SKent Gibson 
906925ca369SKent Gibson 		desc = gpiochip_get_desc(gc, offset);
907925ca369SKent Gibson 		if (IS_ERR(desc))
908925ca369SKent Gibson 			return PTR_ERR(desc);
909925ca369SKent Gibson 
910925ca369SKent Gibson 		hwgpio = gpio_chip_hwgpio(desc);
911925ca369SKent Gibson 
912925ca369SKent Gibson 		if (!test_bit(hwgpio, priv->watched_lines))
913925ca369SKent Gibson 			return -EBUSY;
914925ca369SKent Gibson 
915925ca369SKent Gibson 		clear_bit(hwgpio, priv->watched_lines);
916925ca369SKent Gibson 		return 0;
917925ca369SKent Gibson 	}
918925ca369SKent Gibson 	return -EINVAL;
919925ca369SKent Gibson }
920925ca369SKent Gibson 
921925ca369SKent Gibson #ifdef CONFIG_COMPAT
922*49bc5279SKent Gibson static long gpio_ioctl_compat(struct file *file, unsigned int cmd,
923925ca369SKent Gibson 			      unsigned long arg)
924925ca369SKent Gibson {
925*49bc5279SKent Gibson 	return gpio_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
926925ca369SKent Gibson }
927925ca369SKent Gibson #endif
928925ca369SKent Gibson 
929925ca369SKent Gibson static struct gpio_chardev_data *
930925ca369SKent Gibson to_gpio_chardev_data(struct notifier_block *nb)
931925ca369SKent Gibson {
932925ca369SKent Gibson 	return container_of(nb, struct gpio_chardev_data, lineinfo_changed_nb);
933925ca369SKent Gibson }
934925ca369SKent Gibson 
935925ca369SKent Gibson static int lineinfo_changed_notify(struct notifier_block *nb,
936925ca369SKent Gibson 				   unsigned long action, void *data)
937925ca369SKent Gibson {
938925ca369SKent Gibson 	struct gpio_chardev_data *priv = to_gpio_chardev_data(nb);
939925ca369SKent Gibson 	struct gpioline_info_changed chg;
940925ca369SKent Gibson 	struct gpio_desc *desc = data;
941925ca369SKent Gibson 	int ret;
942925ca369SKent Gibson 
943925ca369SKent Gibson 	if (!test_bit(gpio_chip_hwgpio(desc), priv->watched_lines))
944925ca369SKent Gibson 		return NOTIFY_DONE;
945925ca369SKent Gibson 
946925ca369SKent Gibson 	memset(&chg, 0, sizeof(chg));
947925ca369SKent Gibson 	chg.info.line_offset = gpio_chip_hwgpio(desc);
948925ca369SKent Gibson 	chg.event_type = action;
949925ca369SKent Gibson 	chg.timestamp = ktime_get_ns();
950925ca369SKent Gibson 	gpio_desc_to_lineinfo(desc, &chg.info);
951925ca369SKent Gibson 
952925ca369SKent Gibson 	ret = kfifo_in_spinlocked(&priv->events, &chg, 1, &priv->wait.lock);
953925ca369SKent Gibson 	if (ret)
954925ca369SKent Gibson 		wake_up_poll(&priv->wait, EPOLLIN);
955925ca369SKent Gibson 	else
956925ca369SKent Gibson 		pr_debug_ratelimited("lineinfo event FIFO is full - event dropped\n");
957925ca369SKent Gibson 
958925ca369SKent Gibson 	return NOTIFY_OK;
959925ca369SKent Gibson }
960925ca369SKent Gibson 
961*49bc5279SKent Gibson static __poll_t lineinfo_watch_poll(struct file *file,
962925ca369SKent Gibson 				    struct poll_table_struct *pollt)
963925ca369SKent Gibson {
964*49bc5279SKent Gibson 	struct gpio_chardev_data *priv = file->private_data;
965925ca369SKent Gibson 	__poll_t events = 0;
966925ca369SKent Gibson 
967*49bc5279SKent Gibson 	poll_wait(file, &priv->wait, pollt);
968925ca369SKent Gibson 
969925ca369SKent Gibson 	if (!kfifo_is_empty_spinlocked_noirqsave(&priv->events,
970925ca369SKent Gibson 						 &priv->wait.lock))
971925ca369SKent Gibson 		events = EPOLLIN | EPOLLRDNORM;
972925ca369SKent Gibson 
973925ca369SKent Gibson 	return events;
974925ca369SKent Gibson }
975925ca369SKent Gibson 
976*49bc5279SKent Gibson static ssize_t lineinfo_watch_read(struct file *file, char __user *buf,
977925ca369SKent Gibson 				   size_t count, loff_t *off)
978925ca369SKent Gibson {
979*49bc5279SKent Gibson 	struct gpio_chardev_data *priv = file->private_data;
980925ca369SKent Gibson 	struct gpioline_info_changed event;
981925ca369SKent Gibson 	ssize_t bytes_read = 0;
982925ca369SKent Gibson 	int ret;
983925ca369SKent Gibson 
984925ca369SKent Gibson 	if (count < sizeof(event))
985925ca369SKent Gibson 		return -EINVAL;
986925ca369SKent Gibson 
987925ca369SKent Gibson 	do {
988925ca369SKent Gibson 		spin_lock(&priv->wait.lock);
989925ca369SKent Gibson 		if (kfifo_is_empty(&priv->events)) {
990925ca369SKent Gibson 			if (bytes_read) {
991925ca369SKent Gibson 				spin_unlock(&priv->wait.lock);
992925ca369SKent Gibson 				return bytes_read;
993925ca369SKent Gibson 			}
994925ca369SKent Gibson 
995*49bc5279SKent Gibson 			if (file->f_flags & O_NONBLOCK) {
996925ca369SKent Gibson 				spin_unlock(&priv->wait.lock);
997925ca369SKent Gibson 				return -EAGAIN;
998925ca369SKent Gibson 			}
999925ca369SKent Gibson 
1000925ca369SKent Gibson 			ret = wait_event_interruptible_locked(priv->wait,
1001925ca369SKent Gibson 					!kfifo_is_empty(&priv->events));
1002925ca369SKent Gibson 			if (ret) {
1003925ca369SKent Gibson 				spin_unlock(&priv->wait.lock);
1004925ca369SKent Gibson 				return ret;
1005925ca369SKent Gibson 			}
1006925ca369SKent Gibson 		}
1007925ca369SKent Gibson 
1008925ca369SKent Gibson 		ret = kfifo_out(&priv->events, &event, 1);
1009925ca369SKent Gibson 		spin_unlock(&priv->wait.lock);
1010925ca369SKent Gibson 		if (ret != 1) {
1011925ca369SKent Gibson 			ret = -EIO;
1012925ca369SKent Gibson 			break;
1013925ca369SKent Gibson 			/* We should never get here. See lineevent_read(). */
1014925ca369SKent Gibson 		}
1015925ca369SKent Gibson 
1016925ca369SKent Gibson 		if (copy_to_user(buf + bytes_read, &event, sizeof(event)))
1017925ca369SKent Gibson 			return -EFAULT;
1018925ca369SKent Gibson 		bytes_read += sizeof(event);
1019925ca369SKent Gibson 	} while (count >= bytes_read + sizeof(event));
1020925ca369SKent Gibson 
1021925ca369SKent Gibson 	return bytes_read;
1022925ca369SKent Gibson }
1023925ca369SKent Gibson 
1024925ca369SKent Gibson /**
1025925ca369SKent Gibson  * gpio_chrdev_open() - open the chardev for ioctl operations
1026925ca369SKent Gibson  * @inode: inode for this chardev
1027*49bc5279SKent Gibson  * @file: file struct for storing private data
1028925ca369SKent Gibson  * Returns 0 on success
1029925ca369SKent Gibson  */
1030*49bc5279SKent Gibson static int gpio_chrdev_open(struct inode *inode, struct file *file)
1031925ca369SKent Gibson {
1032925ca369SKent Gibson 	struct gpio_device *gdev = container_of(inode->i_cdev,
1033925ca369SKent Gibson 						struct gpio_device, chrdev);
1034925ca369SKent Gibson 	struct gpio_chardev_data *priv;
1035925ca369SKent Gibson 	int ret = -ENOMEM;
1036925ca369SKent Gibson 
1037925ca369SKent Gibson 	/* Fail on open if the backing gpiochip is gone */
1038925ca369SKent Gibson 	if (!gdev->chip)
1039925ca369SKent Gibson 		return -ENODEV;
1040925ca369SKent Gibson 
1041925ca369SKent Gibson 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
1042925ca369SKent Gibson 	if (!priv)
1043925ca369SKent Gibson 		return -ENOMEM;
1044925ca369SKent Gibson 
1045925ca369SKent Gibson 	priv->watched_lines = bitmap_zalloc(gdev->chip->ngpio, GFP_KERNEL);
1046925ca369SKent Gibson 	if (!priv->watched_lines)
1047925ca369SKent Gibson 		goto out_free_priv;
1048925ca369SKent Gibson 
1049925ca369SKent Gibson 	init_waitqueue_head(&priv->wait);
1050925ca369SKent Gibson 	INIT_KFIFO(priv->events);
1051925ca369SKent Gibson 	priv->gdev = gdev;
1052925ca369SKent Gibson 
1053925ca369SKent Gibson 	priv->lineinfo_changed_nb.notifier_call = lineinfo_changed_notify;
1054925ca369SKent Gibson 	ret = atomic_notifier_chain_register(&gdev->notifier,
1055925ca369SKent Gibson 					     &priv->lineinfo_changed_nb);
1056925ca369SKent Gibson 	if (ret)
1057925ca369SKent Gibson 		goto out_free_bitmap;
1058925ca369SKent Gibson 
1059925ca369SKent Gibson 	get_device(&gdev->dev);
1060*49bc5279SKent Gibson 	file->private_data = priv;
1061925ca369SKent Gibson 
1062*49bc5279SKent Gibson 	ret = nonseekable_open(inode, file);
1063925ca369SKent Gibson 	if (ret)
1064925ca369SKent Gibson 		goto out_unregister_notifier;
1065925ca369SKent Gibson 
1066925ca369SKent Gibson 	return ret;
1067925ca369SKent Gibson 
1068925ca369SKent Gibson out_unregister_notifier:
1069925ca369SKent Gibson 	atomic_notifier_chain_unregister(&gdev->notifier,
1070925ca369SKent Gibson 					 &priv->lineinfo_changed_nb);
1071925ca369SKent Gibson out_free_bitmap:
1072925ca369SKent Gibson 	bitmap_free(priv->watched_lines);
1073925ca369SKent Gibson out_free_priv:
1074925ca369SKent Gibson 	kfree(priv);
1075925ca369SKent Gibson 	return ret;
1076925ca369SKent Gibson }
1077925ca369SKent Gibson 
1078925ca369SKent Gibson /**
1079925ca369SKent Gibson  * gpio_chrdev_release() - close chardev after ioctl operations
1080925ca369SKent Gibson  * @inode: inode for this chardev
1081*49bc5279SKent Gibson  * @file: file struct for storing private data
1082925ca369SKent Gibson  * Returns 0 on success
1083925ca369SKent Gibson  */
1084*49bc5279SKent Gibson static int gpio_chrdev_release(struct inode *inode, struct file *file)
1085925ca369SKent Gibson {
1086*49bc5279SKent Gibson 	struct gpio_chardev_data *priv = file->private_data;
1087925ca369SKent Gibson 	struct gpio_device *gdev = priv->gdev;
1088925ca369SKent Gibson 
1089925ca369SKent Gibson 	bitmap_free(priv->watched_lines);
1090925ca369SKent Gibson 	atomic_notifier_chain_unregister(&gdev->notifier,
1091925ca369SKent Gibson 					 &priv->lineinfo_changed_nb);
1092925ca369SKent Gibson 	put_device(&gdev->dev);
1093925ca369SKent Gibson 	kfree(priv);
1094925ca369SKent Gibson 
1095925ca369SKent Gibson 	return 0;
1096925ca369SKent Gibson }
1097925ca369SKent Gibson 
1098925ca369SKent Gibson static const struct file_operations gpio_fileops = {
1099925ca369SKent Gibson 	.release = gpio_chrdev_release,
1100925ca369SKent Gibson 	.open = gpio_chrdev_open,
1101925ca369SKent Gibson 	.poll = lineinfo_watch_poll,
1102925ca369SKent Gibson 	.read = lineinfo_watch_read,
1103925ca369SKent Gibson 	.owner = THIS_MODULE,
1104925ca369SKent Gibson 	.llseek = no_llseek,
1105925ca369SKent Gibson 	.unlocked_ioctl = gpio_ioctl,
1106925ca369SKent Gibson #ifdef CONFIG_COMPAT
1107925ca369SKent Gibson 	.compat_ioctl = gpio_ioctl_compat,
1108925ca369SKent Gibson #endif
1109925ca369SKent Gibson };
1110925ca369SKent Gibson 
1111925ca369SKent Gibson int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt)
1112925ca369SKent Gibson {
1113925ca369SKent Gibson 	int ret;
1114925ca369SKent Gibson 
1115925ca369SKent Gibson 	cdev_init(&gdev->chrdev, &gpio_fileops);
1116925ca369SKent Gibson 	gdev->chrdev.owner = THIS_MODULE;
1117925ca369SKent Gibson 	gdev->dev.devt = MKDEV(MAJOR(devt), gdev->id);
1118925ca369SKent Gibson 
1119925ca369SKent Gibson 	ret = cdev_device_add(&gdev->chrdev, &gdev->dev);
1120925ca369SKent Gibson 	if (ret)
1121925ca369SKent Gibson 		return ret;
1122925ca369SKent Gibson 
1123925ca369SKent Gibson 	chip_dbg(gdev->chip, "added GPIO chardev (%d:%d)\n",
1124925ca369SKent Gibson 		 MAJOR(devt), gdev->id);
1125925ca369SKent Gibson 
1126925ca369SKent Gibson 	return 0;
1127925ca369SKent Gibson }
1128925ca369SKent Gibson 
1129925ca369SKent Gibson void gpiolib_cdev_unregister(struct gpio_device *gdev)
1130925ca369SKent Gibson {
1131925ca369SKent Gibson 	cdev_device_del(&gdev->chrdev, &gdev->dev);
1132925ca369SKent Gibson }
1133