Skip to content

Commit e588bb1

Browse files
warthog618brgl
authored andcommitted
gpio: add new SET_CONFIG ioctl() to gpio chardev
Add the GPIOHANDLE_SET_CONFIG_IOCTL to the gpio chardev. The ioctl allows some of the configuration of a requested handle to be changed without having to release the line. The primary use case is the changing of direction for bi-directional lines. Based on initial work by Bartosz Golaszewski <bgolaszewski@baylibre.com> Signed-off-by: Kent Gibson <warthog618@gmail.com> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
1 parent b043ed7 commit e588bb1

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

drivers/gpio/gpiolib.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,73 @@ static int linehandle_validate_flags(u32 flags)
476476
return 0;
477477
}
478478

479+
static void linehandle_configure_flag(unsigned long *flagsp,
480+
u32 bit, bool active)
481+
{
482+
if (active)
483+
set_bit(bit, flagsp);
484+
else
485+
clear_bit(bit, flagsp);
486+
}
487+
488+
static long linehandle_set_config(struct linehandle_state *lh,
489+
void __user *ip)
490+
{
491+
struct gpiohandle_config gcnf;
492+
struct gpio_desc *desc;
493+
int i, ret;
494+
u32 lflags;
495+
unsigned long *flagsp;
496+
497+
if (copy_from_user(&gcnf, ip, sizeof(gcnf)))
498+
return -EFAULT;
499+
500+
lflags = gcnf.flags;
501+
ret = linehandle_validate_flags(lflags);
502+
if (ret)
503+
return ret;
504+
505+
for (i = 0; i < lh->numdescs; i++) {
506+
desc = lh->descs[i];
507+
flagsp = &desc->flags;
508+
509+
linehandle_configure_flag(flagsp, FLAG_ACTIVE_LOW,
510+
lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW);
511+
512+
linehandle_configure_flag(flagsp, FLAG_OPEN_DRAIN,
513+
lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN);
514+
515+
linehandle_configure_flag(flagsp, FLAG_OPEN_SOURCE,
516+
lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE);
517+
518+
linehandle_configure_flag(flagsp, FLAG_PULL_UP,
519+
lflags & GPIOHANDLE_REQUEST_BIAS_PULL_UP);
520+
521+
linehandle_configure_flag(flagsp, FLAG_PULL_DOWN,
522+
lflags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN);
523+
524+
linehandle_configure_flag(flagsp, FLAG_BIAS_DISABLE,
525+
lflags & GPIOHANDLE_REQUEST_BIAS_DISABLE);
526+
527+
/*
528+
* Lines have to be requested explicitly for input
529+
* or output, else the line will be treated "as is".
530+
*/
531+
if (lflags & GPIOHANDLE_REQUEST_OUTPUT) {
532+
int val = !!gcnf.default_values[i];
533+
534+
ret = gpiod_direction_output(desc, val);
535+
if (ret)
536+
return ret;
537+
} else if (lflags & GPIOHANDLE_REQUEST_INPUT) {
538+
ret = gpiod_direction_input(desc);
539+
if (ret)
540+
return ret;
541+
}
542+
}
543+
return 0;
544+
}
545+
479546
static long linehandle_ioctl(struct file *filep, unsigned int cmd,
480547
unsigned long arg)
481548
{
@@ -526,6 +593,8 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd,
526593
lh->descs,
527594
NULL,
528595
vals);
596+
} else if (cmd == GPIOHANDLE_SET_CONFIG_IOCTL) {
597+
return linehandle_set_config(lh, ip);
529598
}
530599
return -EINVAL;
531600
}

include/uapi/linux/gpio.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,24 @@ struct gpiohandle_request {
100100
int fd;
101101
};
102102

103+
/**
104+
* struct gpiohandle_config - Configuration for a GPIO handle request
105+
* @flags: updated flags for the requested GPIO lines, such as
106+
* GPIOHANDLE_REQUEST_OUTPUT, GPIOHANDLE_REQUEST_ACTIVE_LOW etc, OR:ed
107+
* together
108+
* @default_values: if the GPIOHANDLE_REQUEST_OUTPUT is set in flags,
109+
* this specifies the default output value, should be 0 (low) or
110+
* 1 (high), anything else than 0 or 1 will be interpreted as 1 (high)
111+
* @padding: reserved for future use and should be zero filled
112+
*/
113+
struct gpiohandle_config {
114+
__u32 flags;
115+
__u8 default_values[GPIOHANDLES_MAX];
116+
__u32 padding[4]; /* padding for future use */
117+
};
118+
119+
#define GPIOHANDLE_SET_CONFIG_IOCTL _IOWR(0xB4, 0x0a, struct gpiohandle_config)
120+
103121
/**
104122
* struct gpiohandle_data - Information of values on a GPIO handle
105123
* @values: when getting the state of lines this contains the current

0 commit comments

Comments
 (0)