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>
This commit is contained in:
parent
b043ed7ef0
commit
e588bb1eae
2 changed files with 87 additions and 0 deletions
|
@ -476,6 +476,73 @@ static int linehandle_validate_flags(u32 flags)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void linehandle_configure_flag(unsigned long *flagsp,
|
||||||
|
u32 bit, bool active)
|
||||||
|
{
|
||||||
|
if (active)
|
||||||
|
set_bit(bit, flagsp);
|
||||||
|
else
|
||||||
|
clear_bit(bit, flagsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long linehandle_set_config(struct linehandle_state *lh,
|
||||||
|
void __user *ip)
|
||||||
|
{
|
||||||
|
struct gpiohandle_config gcnf;
|
||||||
|
struct gpio_desc *desc;
|
||||||
|
int i, ret;
|
||||||
|
u32 lflags;
|
||||||
|
unsigned long *flagsp;
|
||||||
|
|
||||||
|
if (copy_from_user(&gcnf, ip, sizeof(gcnf)))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
lflags = gcnf.flags;
|
||||||
|
ret = linehandle_validate_flags(lflags);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
for (i = 0; i < lh->numdescs; i++) {
|
||||||
|
desc = lh->descs[i];
|
||||||
|
flagsp = &desc->flags;
|
||||||
|
|
||||||
|
linehandle_configure_flag(flagsp, FLAG_ACTIVE_LOW,
|
||||||
|
lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW);
|
||||||
|
|
||||||
|
linehandle_configure_flag(flagsp, FLAG_OPEN_DRAIN,
|
||||||
|
lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN);
|
||||||
|
|
||||||
|
linehandle_configure_flag(flagsp, FLAG_OPEN_SOURCE,
|
||||||
|
lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE);
|
||||||
|
|
||||||
|
linehandle_configure_flag(flagsp, FLAG_PULL_UP,
|
||||||
|
lflags & GPIOHANDLE_REQUEST_BIAS_PULL_UP);
|
||||||
|
|
||||||
|
linehandle_configure_flag(flagsp, FLAG_PULL_DOWN,
|
||||||
|
lflags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN);
|
||||||
|
|
||||||
|
linehandle_configure_flag(flagsp, FLAG_BIAS_DISABLE,
|
||||||
|
lflags & GPIOHANDLE_REQUEST_BIAS_DISABLE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lines have to be requested explicitly for input
|
||||||
|
* or output, else the line will be treated "as is".
|
||||||
|
*/
|
||||||
|
if (lflags & GPIOHANDLE_REQUEST_OUTPUT) {
|
||||||
|
int val = !!gcnf.default_values[i];
|
||||||
|
|
||||||
|
ret = gpiod_direction_output(desc, val);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
} else if (lflags & GPIOHANDLE_REQUEST_INPUT) {
|
||||||
|
ret = gpiod_direction_input(desc);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static long linehandle_ioctl(struct file *filep, unsigned int cmd,
|
static long linehandle_ioctl(struct file *filep, unsigned int cmd,
|
||||||
unsigned long arg)
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
|
@ -526,6 +593,8 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd,
|
||||||
lh->descs,
|
lh->descs,
|
||||||
NULL,
|
NULL,
|
||||||
vals);
|
vals);
|
||||||
|
} else if (cmd == GPIOHANDLE_SET_CONFIG_IOCTL) {
|
||||||
|
return linehandle_set_config(lh, ip);
|
||||||
}
|
}
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,24 @@ struct gpiohandle_request {
|
||||||
int fd;
|
int fd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct gpiohandle_config - Configuration for a GPIO handle request
|
||||||
|
* @flags: updated flags for the requested GPIO lines, such as
|
||||||
|
* GPIOHANDLE_REQUEST_OUTPUT, GPIOHANDLE_REQUEST_ACTIVE_LOW etc, OR:ed
|
||||||
|
* together
|
||||||
|
* @default_values: if the GPIOHANDLE_REQUEST_OUTPUT is set in flags,
|
||||||
|
* this specifies the default output value, should be 0 (low) or
|
||||||
|
* 1 (high), anything else than 0 or 1 will be interpreted as 1 (high)
|
||||||
|
* @padding: reserved for future use and should be zero filled
|
||||||
|
*/
|
||||||
|
struct gpiohandle_config {
|
||||||
|
__u32 flags;
|
||||||
|
__u8 default_values[GPIOHANDLES_MAX];
|
||||||
|
__u32 padding[4]; /* padding for future use */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GPIOHANDLE_SET_CONFIG_IOCTL _IOWR(0xB4, 0x0a, struct gpiohandle_config)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct gpiohandle_data - Information of values on a GPIO handle
|
* struct gpiohandle_data - Information of values on a GPIO handle
|
||||||
* @values: when getting the state of lines this contains the current
|
* @values: when getting the state of lines this contains the current
|
||||||
|
|
Loading…
Add table
Reference in a new issue