From: Kent Gibson <warthog618@gmail.com>
To: linux-gpio@vger.kernel.org, bgolaszewski@baylibre.com,
linus.walleij@linaro.org
Cc: Kent Gibson <warthog618@gmail.com>
Subject: [PATCH v2 2/2] gpio: add new SET_CONFIG ioctl() to gpio chardev
Date: Thu, 31 Oct 2019 22:48:25 +0800 [thread overview]
Message-ID: <20191031144825.32105-3-warthog618@gmail.com> (raw)
In-Reply-To: <20191031144825.32105-1-warthog618@gmail.com>
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>
---
drivers/gpio/gpiolib.c | 68 +++++++++++++++++++++++++++++++++++++++
include/uapi/linux/gpio.h | 18 +++++++++++
2 files changed, 86 insertions(+)
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 4e8fbd74a29c..7c026ee58917 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -475,6 +475,73 @@ static int linehandle_validate_flags(u32 flags)
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,
unsigned long arg)
{
@@ -525,6 +592,8 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd,
lh->descs,
NULL,
vals);
+ } else if (cmd == GPIOHANDLE_SET_CONFIG_IOCTL) {
+ return linehandle_set_config(lh, ip);
}
return -EINVAL;
}
diff --git a/include/uapi/linux/gpio.h b/include/uapi/linux/gpio.h
index 7cc21c3b0839..799cf823d493 100644
--- a/include/uapi/linux/gpio.h
+++ b/include/uapi/linux/gpio.h
@@ -100,6 +100,24 @@ struct gpiohandle_request {
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
* @values: when getting the state of lines this contains the current
--
2.23.0
next prev parent reply other threads:[~2019-10-31 14:49 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-10-31 14:48 [PATCH v2 0/2] gpio: add new SET_CONFIG ioctl() to gpio chardev Kent Gibson
2019-10-31 14:48 ` [PATCH v2 1/2] gpiolib: move validation of line handle flags into helper function Kent Gibson
2019-10-31 14:48 ` Kent Gibson [this message]
2019-11-02 21:02 ` [PATCH v2 0/2] gpio: add new SET_CONFIG ioctl() to gpio chardev Drew Fustini
2019-11-02 23:14 ` Kent Gibson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191031144825.32105-3-warthog618@gmail.com \
--to=warthog618@gmail.com \
--cc=bgolaszewski@baylibre.com \
--cc=linus.walleij@linaro.org \
--cc=linux-gpio@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.