All of lore.kernel.org
 help / color / mirror / Atom feed
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


  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 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.