From: Ben Gardner <gardner.ben@gmail.com>
To: linux-kernel@vger.kernel.org,
Andres Salomon <dilinger@collabora.co.uk>,
Andrew Morton <akpm@linux-foundation.org>
Cc: Ben Gardner <gardner.ben@gmail.com>,
Andres Salomon <dilinger@collabora.co.uk>,
Andrew Morton <akpm@linux-foundation.org>,
David Brownell <dbrownell@users.sourceforge.net>,
Jani Nikula <ext-jani.1.nikula@nokia.com>
Subject: [PATCH 1/3] gpiolib: add gpio_set_direction()
Date: Fri, 26 Feb 2010 17:26:24 -0600 [thread overview]
Message-ID: <14e456b7d269efd860bb36c312de2bc4ad504dca.1267225701.git.gardner.ben@gmail.com> (raw)
In-Reply-To: <cover.1267225701.git.gardner.ben@gmail.com>
In-Reply-To: <cover.1267225701.git.gardner.ben@gmail.com>
Combine gpio_direction_input() and gpio_direction_output() into
gpio_set_direction().
Add 'none' and 'inout' directions to the sysfs interface.
Signed-off-by: Ben Gardner <gardner.ben@gmail.com>
CC: Andres Salomon <dilinger@collabora.co.uk>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: David Brownell <dbrownell@users.sourceforge.net>
CC: Jani Nikula <ext-jani.1.nikula@nokia.com>
---
drivers/gpio/gpiolib.c | 123 ++++++++++++++++++++++----------------------
include/asm-generic/gpio.h | 6 ++
include/linux/gpio.h | 5 ++
3 files changed, 73 insertions(+), 61 deletions(-)
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 350842a..4dd6e44 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -47,13 +47,14 @@ struct gpio_desc {
unsigned long flags;
/* flag symbols are bit numbers */
#define FLAG_REQUESTED 0
-#define FLAG_IS_OUT 1
+#define FLAG_IS_OUT 1 /* output is enabled */
#define FLAG_RESERVED 2
#define FLAG_EXPORT 3 /* protected by sysfs_lock */
#define FLAG_SYSFS 4 /* exported via /sys/class/gpio/control */
#define FLAG_TRIG_FALL 5 /* trigger on falling edge */
#define FLAG_TRIG_RISE 6 /* trigger on rising edge */
#define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */
+#define FLAG_IS_IN 8 /* input is enabled */
#define PDESC_ID_SHIFT 16 /* add new flags before this one */
@@ -228,10 +229,14 @@ static ssize_t gpio_direction_show(struct device *dev,
if (!test_bit(FLAG_EXPORT, &desc->flags))
status = -EIO;
- else
- status = sprintf(buf, "%s\n",
- test_bit(FLAG_IS_OUT, &desc->flags)
- ? "out" : "in");
+ else {
+ status = ((test_bit(FLAG_IS_IN, &desc->flags) ? 1 : 0) |
+ (test_bit(FLAG_IS_OUT, &desc->flags) ? 2 : 0));
+ status = sprintf(buf, "%s%s%s\n",
+ (status == 0) ? "none" : "",
+ (status & 1) ? "in" : "",
+ (status & 2) ? "out" : "");
+ }
mutex_unlock(&sysfs_lock);
return status;
@@ -249,11 +254,15 @@ static ssize_t gpio_direction_store(struct device *dev,
if (!test_bit(FLAG_EXPORT, &desc->flags))
status = -EIO;
else if (sysfs_streq(buf, "high"))
- status = gpio_direction_output(gpio, 1);
+ status = gpio_set_direction(gpio, 2, 1);
else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low"))
- status = gpio_direction_output(gpio, 0);
+ status = gpio_set_direction(gpio, 2, 0);
else if (sysfs_streq(buf, "in"))
- status = gpio_direction_input(gpio);
+ status = gpio_set_direction(gpio, 1, 0);
+ else if (sysfs_streq(buf, "inout"))
+ status = gpio_set_direction(gpio, 3, 0);
+ else if (sysfs_streq(buf, "none"))
+ status = gpio_set_direction(gpio, 0, 0);
else
status = -EINVAL;
@@ -1277,7 +1286,7 @@ EXPORT_SYMBOL_GPL(gpiochip_is_requested);
* rely on gpio_request() having been called beforehand.
*/
-int gpio_direction_input(unsigned gpio)
+int gpio_set_direction(unsigned gpio, int direction, int value)
{
unsigned long flags;
struct gpio_chip *chip;
@@ -1289,7 +1298,13 @@ int gpio_direction_input(unsigned gpio)
if (!gpio_is_valid(gpio))
goto fail;
chip = desc->chip;
- if (!chip || !chip->get || !chip->direction_input)
+ if (!chip)
+ goto fail;
+ if ((direction & 1) &&
+ (!chip->get || (!chip->direction_input && !chip->set_direction)))
+ goto fail;
+ if ((direction & 2) &&
+ (!chip->set || (!chip->direction_output && !chip->set_direction)))
goto fail;
gpio -= chip->base;
if (gpio >= chip->ngpio)
@@ -1316,9 +1331,36 @@ int gpio_direction_input(unsigned gpio)
}
}
- status = chip->direction_input(chip, gpio);
- if (status == 0)
- clear_bit(FLAG_IS_OUT, &desc->flags);
+ if (chip->set_direction) {
+ status = chip->set_direction(chip, gpio, direction, value);
+ if (status == 0) {
+ if (direction & 1)
+ set_bit(FLAG_IS_IN, &desc->flags);
+ else
+ clear_bit(FLAG_IS_IN, &desc->flags);
+ if (direction & 2)
+ set_bit(FLAG_IS_OUT, &desc->flags);
+ else
+ clear_bit(FLAG_IS_OUT, &desc->flags);
+ }
+ }
+ else if (direction == 1) {
+ status = chip->direction_input(chip, gpio);
+ if (status == 0) {
+ clear_bit(FLAG_IS_OUT, &desc->flags);
+ set_bit(FLAG_IS_IN, &desc->flags);
+ }
+ }
+ else if (direction == 2) {
+ status = chip->direction_output(chip, gpio, value);
+ if (status == 0) {
+ clear_bit(FLAG_IS_IN, &desc->flags);
+ set_bit(FLAG_IS_OUT, &desc->flags);
+ }
+ }
+ else
+ /* cannot do 'none' or 'inout' without chip->set_direction */
+ status = -ENOTSUPP;
lose:
return status;
fail:
@@ -1328,58 +1370,17 @@ fail:
__func__, gpio, status);
return status;
}
+EXPORT_SYMBOL_GPL(gpio_set_direction);
+
+int gpio_direction_input(unsigned gpio)
+{
+ return gpio_set_direction(gpio, 1, 0);
+}
EXPORT_SYMBOL_GPL(gpio_direction_input);
int gpio_direction_output(unsigned gpio, int value)
{
- unsigned long flags;
- struct gpio_chip *chip;
- struct gpio_desc *desc = &gpio_desc[gpio];
- int status = -EINVAL;
-
- spin_lock_irqsave(&gpio_lock, flags);
-
- if (!gpio_is_valid(gpio))
- goto fail;
- chip = desc->chip;
- if (!chip || !chip->set || !chip->direction_output)
- goto fail;
- gpio -= chip->base;
- if (gpio >= chip->ngpio)
- goto fail;
- status = gpio_ensure_requested(desc, gpio);
- if (status < 0)
- goto fail;
-
- /* now we know the gpio is valid and chip won't vanish */
-
- spin_unlock_irqrestore(&gpio_lock, flags);
-
- might_sleep_if(extra_checks && chip->can_sleep);
-
- if (status) {
- status = chip->request(chip, gpio);
- if (status < 0) {
- pr_debug("GPIO-%d: chip request fail, %d\n",
- chip->base + gpio, status);
- /* and it's not available to anyone else ...
- * gpio_request() is the fully clean solution.
- */
- goto lose;
- }
- }
-
- status = chip->direction_output(chip, gpio, value);
- if (status == 0)
- set_bit(FLAG_IS_OUT, &desc->flags);
-lose:
- return status;
-fail:
- spin_unlock_irqrestore(&gpio_lock, flags);
- if (status)
- pr_debug("%s: gpio-%d status %d\n",
- __func__, gpio, status);
- return status;
+ return gpio_set_direction(gpio, 2, value);
}
EXPORT_SYMBOL_GPL(gpio_direction_output);
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 485eeb6..17c7642 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -41,6 +41,8 @@ struct module;
* enabling module power and clock; may sleep
* @free: optional hook for chip-specific deactivation, such as
* disabling module power and clock; may sleep
+ * @set_direction: configures signal "offset" as "direction" (0-3, bit0=input,
+ * bit1=output) or returns error
* @direction_input: configures signal "offset" as input, or returns error
* @get: returns value for signal "offset"; for output signals this
* returns either the value actually sensed, or zero
@@ -82,6 +84,9 @@ struct gpio_chip {
void (*free)(struct gpio_chip *chip,
unsigned offset);
+ int (*set_direction)(struct gpio_chip *chip,
+ unsigned offset,
+ int direction, int value);
int (*direction_input)(struct gpio_chip *chip,
unsigned offset);
int (*get)(struct gpio_chip *chip,
@@ -118,6 +123,7 @@ extern int __must_check gpiochip_remove(struct gpio_chip *chip);
extern int gpio_request(unsigned gpio, const char *label);
extern void gpio_free(unsigned gpio);
+extern int gpio_set_direction(unsigned gpio, int direction, int value);
extern int gpio_direction_input(unsigned gpio);
extern int gpio_direction_output(unsigned gpio, int value);
diff --git a/include/linux/gpio.h b/include/linux/gpio.h
index 4e949a5..cdc2117 100644
--- a/include/linux/gpio.h
+++ b/include/linux/gpio.h
@@ -41,6 +41,11 @@ static inline void gpio_free(unsigned gpio)
WARN_ON(1);
}
+static inline int gpio_set_direction(unsigned gpio, int direction, int value)
+{
+ return -ENOSYS;
+}
+
static inline int gpio_direction_input(unsigned gpio)
{
return -ENOSYS;
--
1.7.0
next prev parent reply other threads:[~2010-02-26 23:27 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-02-26 23:26 [PATCH 0/3] gpio: add gpio_set_direction Ben Gardner
2010-02-26 23:26 ` Ben Gardner [this message]
2010-02-26 23:39 ` [PATCH 1/3] gpiolib: add gpio_set_direction() Andres Salomon
2010-02-27 5:11 ` Ben Gardner
2010-02-27 7:02 ` David Brownell
2010-02-27 10:26 ` Mark Brown
2010-02-27 16:24 ` David Brownell
2010-02-27 17:20 ` Mark Brown
2010-02-27 17:51 ` David Brownell
2010-03-01 10:35 ` Mark Brown
2010-02-27 18:36 ` Ben Gardner
2010-02-27 19:23 ` David Brownell
2010-02-27 18:36 ` [PATCH] cs5535-gpio: change input/output enable to match gpiolib expectations Ben Gardner
2010-02-27 18:40 ` Ben Gardner
2010-02-27 18:56 ` [PATCH v2] " Ben Gardner
2010-02-27 19:18 ` David Brownell
2010-02-26 23:26 ` [PATCH 2/3] cs5535-gpio: Use set_direction Ben Gardner
2010-02-27 7:04 ` David Brownell
2010-02-27 18:18 ` Ben Gardner
2010-02-26 23:26 ` [PATCH 3/3] OLPC: ALSA: fix cs5535audio's MIC GPIO to enable input Ben Gardner
2010-02-27 7:14 ` David Brownell
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=14e456b7d269efd860bb36c312de2bc4ad504dca.1267225701.git.gardner.ben@gmail.com \
--to=gardner.ben@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=dbrownell@users.sourceforge.net \
--cc=dilinger@collabora.co.uk \
--cc=ext-jani.1.nikula@nokia.com \
--cc=linux-kernel@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®