lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20241119140805.3345412-1-paulk@sys-base.io>
Date: Tue, 19 Nov 2024 15:08:05 +0100
From: Paul Kocialkowski <paulk@...-base.io>
To: linux-arm-kernel@...ts.infradead.org,
	linux-sunxi@...ts.linux.dev,
	linux-kernel@...r.kernel.org
Cc: Uwe Kleine-König <ukleinek@...nel.org>,
	Chen-Yu Tsai <wens@...e.org>,
	Jernej Skrabec <jernej.skrabec@...il.com>,
	Samuel Holland <samuel@...lland.org>,
	Linus Walleij <linus.walleij@...aro.org>,
	Maxime Ripard <mripard@...nel.org>,
	Paul Kocialkowski <contact@...lk.fr>
Subject: [PATCH] pinctrl: sunxi: Use minimal debouncing period as default

From: Paul Kocialkowski <contact@...lk.fr>

The sunxi external interrupts (available from GPIO pins) come with a
built-in debouncing mechanism that cannot be disabled. It can be
configured to use either the low-frequency oscillator (32 KHz) or the
high-frequency oscillator (24 MHz), with a pre-scaler.

The pinctrl code supports an input-debounce device-tree property to set
a specific debouncing period and choose which clock source is most
relevant. However the property is specified in microseconds, which is
longer than the minimal period achievable from the high-frequency
oscillator without a pre-scaler.

When the property is missing, the reset configuration is kept, which
selects the low-frequency oscillator without pre-scaling. This severely
limits the possible interrupt periods that can be detected.

Instead of keeping this default, use the minimal debouncing period from
the high-frequency oscillator without a pre-scaler to allow the largest
possible range of interrupt periods.

This issue was encountered with a peripheral that generates active-low
interrupts for 1 us. No interrupt was detected with the default setup,
while it is now correctly detected with this change.

Signed-off-by: Paul Kocialkowski <contact@...lk.fr>
---
 drivers/pinctrl/sunxi/pinctrl-sunxi.c | 49 ++++++++++++++++-----------
 1 file changed, 29 insertions(+), 20 deletions(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 73bcf806af0e..06c650d97645 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -1416,6 +1416,7 @@ static int sunxi_pinctrl_setup_debounce(struct sunxi_pinctrl *pctl,
 	unsigned int hosc_diff, losc_diff;
 	unsigned int hosc_div, losc_div;
 	struct clk *hosc, *losc;
+	bool debounce_minimal = false;
 	u8 div, src;
 	int i, ret;
 
@@ -1423,9 +1424,9 @@ static int sunxi_pinctrl_setup_debounce(struct sunxi_pinctrl *pctl,
 	if (of_clk_get_parent_count(node) != 3)
 		return 0;
 
-	/* If we don't have any setup, bail out */
+	/* If we don't have any setup, use minimal debouncing. */
 	if (!of_property_present(node, "input-debounce"))
-		return 0;
+		debounce_minimal = true;
 
 	losc = devm_clk_get(pctl->dev, "losc");
 	if (IS_ERR(losc))
@@ -1439,29 +1440,37 @@ static int sunxi_pinctrl_setup_debounce(struct sunxi_pinctrl *pctl,
 		unsigned long debounce_freq;
 		u32 debounce;
 
-		ret = of_property_read_u32_index(node, "input-debounce",
-						 i, &debounce);
-		if (ret)
-			return ret;
+		if (!debounce_minimal) {
+			ret = of_property_read_u32_index(node, "input-debounce",
+							 i, &debounce);
+			if (ret)
+				return ret;
 
-		if (!debounce)
-			continue;
+			if (!debounce)
+				continue;
 
-		debounce_freq = DIV_ROUND_CLOSEST(USEC_PER_SEC, debounce);
-		losc_div = sunxi_pinctrl_get_debounce_div(losc,
-							  debounce_freq,
-							  &losc_diff);
+			debounce_freq = DIV_ROUND_CLOSEST(USEC_PER_SEC,
+							  debounce);
 
-		hosc_div = sunxi_pinctrl_get_debounce_div(hosc,
-							  debounce_freq,
-							  &hosc_diff);
+			losc_div = sunxi_pinctrl_get_debounce_div(losc,
+								  debounce_freq,
+								  &losc_diff);
 
-		if (hosc_diff < losc_diff) {
-			div = hosc_div;
-			src = 1;
+			hosc_div = sunxi_pinctrl_get_debounce_div(hosc,
+								  debounce_freq,
+								  &hosc_diff);
+
+			if (hosc_diff < losc_diff) {
+				div = hosc_div;
+				src = 1;
+			} else {
+				div = losc_div;
+				src = 0;
+			}
 		} else {
-			div = losc_div;
-			src = 0;
+			/* Achieve minimal debouncing using undivided hosc. */
+			div = 0;
+			src = 1;
 		}
 
 		writel(src | div << 4,
-- 
2.47.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ