All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tomer Maimon <tmaimon77@gmail.com>
To: linus.walleij@linaro.org
Cc: linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org,
	Tomer Maimon <tmaimon77@gmail.com>
Subject: [PATCH v1 1/1] gpio: mmio: add inverted direction get_set io support
Date: Mon, 30 Jul 2018 12:34:18 +0300	[thread overview]
Message-ID: <20180730093418.124648-2-tmaimon77@gmail.com> (raw)
In-Reply-To: <20180730093418.124648-1-tmaimon77@gmail.com>

Add get_set_inv_dir and get_set_multiple_inv_dir I/O functions
to call the data register when the dirction is input and
set register when the direction is output.
the functions will linked to the I/O get functions if the user set
BGPIOF_INVERTED_REG_DIR flag in the bgpio initialization.

Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
---
 drivers/gpio/gpio-mmio.c    | 48 ++++++++++++++++++++++++++++++++++++++++++---
 include/linux/gpio/driver.h |  1 +
 2 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index 7b14d6280e44..46f664459853 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -168,6 +168,40 @@ static int bgpio_get_set_multiple(struct gpio_chip *gc, unsigned long *mask,
 	return 0;
 }
 
+/* get set function when the direction is inverted */
+static int bgpio_get_set_inv_dir(struct gpio_chip *gc, unsigned int gpio)
+{
+	unsigned long pinmask = bgpio_line2mask(gc, gpio);
+
+	if (gc->bgpio_dir & pinmask)
+		return !!(gc->read_reg(gc->reg_dat) & pinmask);
+	else
+		return !!(gc->read_reg(gc->reg_set) & pinmask);
+}
+
+/* get set multiple function when the direction is inverted */
+static int bgpio_get_set_multiple_inv_dir(struct gpio_chip *gc,
+					  unsigned long *mask,
+					  unsigned long *bits)
+{
+	unsigned long get_mask = 0;
+	unsigned long set_mask = 0;
+
+	/* Make sure we first clear any bits that are zero when we read the register */
+	*bits &= ~*mask;
+
+	/* Exploit the fact that we know which directions are set */
+	set_mask = *mask & ~gc->bgpio_dir;
+	get_mask = *mask & gc->bgpio_dir;
+
+	if (set_mask)
+		*bits |= gc->read_reg(gc->reg_set) & set_mask;
+	if (get_mask)
+		*bits |= gc->read_reg(gc->reg_dat) & get_mask;
+
+	return 0;
+}
+
 static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
 {
 	return !!(gc->read_reg(gc->reg_dat) & bgpio_line2mask(gc, gpio));
@@ -525,9 +559,17 @@ static int bgpio_setup_io(struct gpio_chip *gc,
 
 	if (!(flags & BGPIOF_UNREADABLE_REG_SET) &&
 	    (flags & BGPIOF_READ_OUTPUT_REG_SET)) {
-		gc->get = bgpio_get_set;
-		if (!gc->be_bits)
-			gc->get_multiple = bgpio_get_set_multiple;
+		/* if the direction inverted */
+		if (flags & BGPIOF_INVERTED_REG_DIR) {
+			gc->get = bgpio_get_set_inv_dir;
+			if (!gc->be_bits)
+				gc->get_multiple =
+				bgpio_get_set_multiple_inv_dir;
+		} else {
+			gc->get = bgpio_get_set;
+			if (!gc->be_bits)
+				gc->get_multiple = bgpio_get_set_multiple;
+		}
 		/*
 		 * We deliberately avoid assigning the ->get_multiple() call
 		 * for big endian mirrored registers which are ALSO reflecting
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index 5382b5183b7e..63570580707c 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -425,6 +425,7 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev,
 #define BGPIOF_BIG_ENDIAN_BYTE_ORDER	BIT(3)
 #define BGPIOF_READ_OUTPUT_REG_SET	BIT(4) /* reg_set stores output value */
 #define BGPIOF_NO_OUTPUT		BIT(5) /* only input */
+#define BGPIOF_INVERTED_REG_DIR		BIT(6) /* reg_dir inverted */
 
 #endif
 
-- 
2.14.1

  reply	other threads:[~2018-07-30  9:34 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-30  9:34 [PATCH v1 0/1] gpio: mmio: add get_set inverted direction io support Tomer Maimon
2018-07-30  9:34 ` Tomer Maimon [this message]
2018-07-30 17:14   ` [PATCH v1 1/1] gpio: mmio: add inverted direction get_set " Andy Shevchenko
2018-08-02 23:34   ` Linus Walleij

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=20180730093418.124648-2-tmaimon77@gmail.com \
    --to=tmaimon77@gmail.com \
    --cc=linus.walleij@linaro.org \
    --cc=linux-gpio@vger.kernel.org \
    --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.