Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1602984 > unrolled thread

[PATCH 0/2] gpio: omap: set_debounce fixes

Started byDavid Rivshin <drivshin@awxrd.com>
First post2017-03-17 03:00 +0100
Last post2017-03-17 03:00 +0100
Articles 3 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [PATCH 0/2] gpio: omap: set_debounce fixes David Rivshin <drivshin@awxrd.com> - 2017-03-17 03:00 +0100
    [PATCH 1/2] gpio: omap: return error if requested debounce time is not possible David Rivshin <drivshin@awxrd.com> - 2017-03-17 03:00 +0100
    [PATCH 2/2] gpio: omap: compute debounce-time from actual debounce-clock rate David Rivshin <drivshin@awxrd.com> - 2017-03-17 03:00 +0100

#1602984 — [PATCH 0/2] gpio: omap: set_debounce fixes

FromDavid Rivshin <drivshin@awxrd.com>
Date2017-03-17 03:00 +0100
Subject[PATCH 0/2] gpio: omap: set_debounce fixes
Message-ID<tlPln-75t-3@gated-at.bofh.it>
From: David Rivshin <drivshin@allworx.com>

This series fixes a couple of issues in the gpio-omap set_debounce logic.

Patches based ontop of v4.11-rc1, but apply cleanly to linux-gpio/fixes
and linux-next.

Tested on a (custom) AM335x board via gpio-keys.

(Apologies if anyone received this series twice, it seemed to fail
the first time due to a typo. Please ignore the any previous copy.)


David Rivshin (2):
  gpio: omap: return error if requested debounce time is not possible
  gpio: omap: compute debounce-time from actual debounce-clock rate

 drivers/gpio/gpio-omap.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

-- 
2.9.3

base-commit: c1ae3cfa0e89fa1a7ecc4c99031f5e9ae99d9201

[toc] | [next] | [standalone]


#1602985 — [PATCH 1/2] gpio: omap: return error if requested debounce time is not possible

FromDavid Rivshin <drivshin@awxrd.com>
Date2017-03-17 03:00 +0100
Subject[PATCH 1/2] gpio: omap: return error if requested debounce time is not possible
Message-ID<tlPln-75t-7@gated-at.bofh.it>
In reply to#1602984
From: David Rivshin <DRivshin@allworx.com>

omap_gpio_debounce() does not validate that the requested debounce
is within a range it can handle. Instead it lets the register value
wrap silently, and always returns success.

This can lead to all sorts of unexpected behavior, such as gpio_keys
asking for a too-long debounce, but getting a very short debounce in
practice.

Fix this by returning -EINVAL if the requested value does not fit into
the register field. If there is no debounce clock available at all,
return -ENOTSUPP.

Fixes: e85ec6c3047b ("gpio: omap: fix omap2_set_gpio_debounce")
Cc: <stable@vger.kernel.org> # 4.3+
Signed-off-by: David Rivshin <drivshin@allworx.com>
---
 drivers/gpio/gpio-omap.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index efc85a2..c40dbdd 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -208,9 +208,11 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
  * OMAP's debounce time is in 31us steps
  *   <debounce time> = (GPIO_DEBOUNCINGTIME[7:0].DEBOUNCETIME + 1) x 31
  * so we need to convert and round up to the closest unit.
+ *
+ * Return: 0 on success, negative error otherwise.
  */
-static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
-				    unsigned debounce)
+static int omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
+				   unsigned debounce)
 {
 	void __iomem		*reg;
 	u32			val;
@@ -218,11 +220,12 @@ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
 	bool			enable = !!debounce;
 
 	if (!bank->dbck_flag)
-		return;
+		return -ENOTSUPP;
 
 	if (enable) {
 		debounce = DIV_ROUND_UP(debounce, 31) - 1;
-		debounce &= OMAP4_GPIO_DEBOUNCINGTIME_MASK;
+		if ((debounce & OMAP4_GPIO_DEBOUNCINGTIME_MASK) != debounce)
+			return -EINVAL;
 	}
 
 	l = BIT(offset);
@@ -255,6 +258,8 @@ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
 		bank->context.debounce = debounce;
 		bank->context.debounce_en = val;
 	}
+
+	return 0;
 }
 
 /**
@@ -964,14 +969,15 @@ static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,
 {
 	struct gpio_bank *bank;
 	unsigned long flags;
+	int ret;
 
 	bank = gpiochip_get_data(chip);
 
 	raw_spin_lock_irqsave(&bank->lock, flags);
-	omap2_set_gpio_debounce(bank, offset, debounce);
+	ret = omap2_set_gpio_debounce(bank, offset, debounce);
 	raw_spin_unlock_irqrestore(&bank->lock, flags);
 
-	return 0;
+	return ret;
 }
 
 static int omap_gpio_set_config(struct gpio_chip *chip, unsigned offset,
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1602986 — [PATCH 2/2] gpio: omap: compute debounce-time from actual debounce-clock rate

FromDavid Rivshin <drivshin@awxrd.com>
Date2017-03-17 03:00 +0100
Subject[PATCH 2/2] gpio: omap: compute debounce-time from actual debounce-clock rate
Message-ID<tlPln-75t-11@gated-at.bofh.it>
In reply to#1602984
From: David Rivshin <DRivshin@allworx.com>

omap2_set_gpio_debounce() assumes the debounce clock runs at 32768Hz,
leading to 31us granularity. In reality the debounce clock (which
is provided by other modules) could be at different rate, leading to
an incorrect computation of the number of debounce clock cycles for
GPIO_DEBOUNCINGTIME[DEBOUNCETIME].

Also, even with a standard 32768Hz input clock, the actual granularity
is ~30.5us. This leads to the actual debounce time being ~1.5% too
short.

Fix both issues by simply querying the dbck rate, rather than
hardcoding.

Fixes: e85ec6c3047b ("gpio: omap: fix omap2_set_gpio_debounce")
Cc: <stable@vger.kernel.org> # 4.3+
Signed-off-by: David Rivshin <drivshin@allworx.com>
---

This logical bug existed before e85ec6c3047b, but if backporting
further it's probably best to just cherry-pick/backport e85ec6c3047b
first.

 drivers/gpio/gpio-omap.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index c40dbdd..66dbe37 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -205,8 +205,8 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
  * @offset: the gpio number on this @bank
  * @debounce: debounce time to use
  *
- * OMAP's debounce time is in 31us steps
- *   <debounce time> = (GPIO_DEBOUNCINGTIME[7:0].DEBOUNCETIME + 1) x 31
+ * OMAP's debounce time is in 1/DBCK steps
+ *   <debounce time> = (GPIO_DEBOUNCINGTIME[7:0].DEBOUNCETIME + 1) / DBCK
  * so we need to convert and round up to the closest unit.
  *
  * Return: 0 on success, negative error otherwise.
@@ -223,7 +223,9 @@ static int omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
 		return -ENOTSUPP;
 
 	if (enable) {
-		debounce = DIV_ROUND_UP(debounce, 31) - 1;
+		u64 tmp = (u64)debounce * clk_get_rate(bank->dbck);
+
+		debounce = DIV_ROUND_UP_ULL(tmp, 1000000) - 1;
 		if ((debounce & OMAP4_GPIO_DEBOUNCINGTIME_MASK) != debounce)
 			return -EINVAL;
 	}
-- 
2.9.3

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web