[PATCH] cmd: gpio: Add `gpio read` subcommand

Diego Rondini diego.rondini at kynetics.com
Tue Mar 22 18:14:35 CET 2022


As explained in commit 4af2a33ee5b9 ("cmd: gpio: Make `gpio input`
return pin value again") the `gpio input` is used in scripts to obtain
the value of a pin, despite the fact that CMD_RET_FAILURE is
indistinguishable from a valid pin value.
To be able to detect failures and properly use the value of a GPIO in
scripts we introduce the `gpio read` command that sets the variable
`name` to the value of the pin. Return code of the `gpio read` command
can be used to check for CMD_RET_SUCCESS or CMD_RET_FAILURE.

Signed-off-by: Diego Rondini <diego.rondini at kynetics.com>
---
 cmd/gpio.c                 | 24 ++++++++++++++++++++----
 test/py/tests/test_gpio.py | 15 +++++++++++++++
 2 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/cmd/gpio.c b/cmd/gpio.c
index 4150024e628..150c77cbcf9 100644
--- a/cmd/gpio.c
+++ b/cmd/gpio.c
@@ -12,6 +12,7 @@
 #include <dm.h>
 #include <log.h>
 #include <malloc.h>
+#include <env.h>
 #include <asm/gpio.h>
 #include <linux/err.h>
 
@@ -25,6 +26,7 @@ enum gpio_cmd {
 	GPIOC_SET,
 	GPIOC_CLEAR,
 	GPIOC_TOGGLE,
+	GPIOC_READ,
 };
 
 #if defined(CONFIG_DM_GPIO) && !defined(gpio_status)
@@ -124,7 +126,7 @@ static int do_gpio(struct cmd_tbl *cmdtp, int flag, int argc,
 	unsigned int gpio;
 	enum gpio_cmd sub_cmd;
 	int value;
-	const char *str_cmd, *str_gpio = NULL;
+	const char *str_cmd, *str_gpio, *str_var = NULL;
 	int ret;
 #ifdef CONFIG_DM_GPIO
 	bool all = false;
@@ -137,12 +139,19 @@ static int do_gpio(struct cmd_tbl *cmdtp, int flag, int argc,
 	argc -= 2;
 	argv += 2;
 #ifdef CONFIG_DM_GPIO
-	if (argc > 0 && !strcmp(*argv, "-a")) {
+	if (argc > 0 && !strncmp(str_cmd, "status", 2) && !strcmp(*argv, "-a")) {
 		all = true;
 		argc--;
 		argv++;
 	}
 #endif
+	if (argc > 0 && !strncmp(str_cmd, "read", 2)) {
+		if (argc < 2)
+			goto show_usage;
+		str_var = *argv;
+		argc--;
+		argv++;
+	}
 	if (argc > 0)
 		str_gpio = *argv;
 	if (!strncmp(str_cmd, "status", 2)) {
@@ -174,6 +183,9 @@ static int do_gpio(struct cmd_tbl *cmdtp, int flag, int argc,
 	case 't':
 		sub_cmd = GPIOC_TOGGLE;
 		break;
+	case 'r':
+		sub_cmd = GPIOC_READ;
+		break;
 	default:
 		goto show_usage;
 	}
@@ -205,7 +217,7 @@ static int do_gpio(struct cmd_tbl *cmdtp, int flag, int argc,
 	}
 
 	/* finally, let's do it: set direction and exec command */
-	if (sub_cmd == GPIOC_INPUT) {
+	if (sub_cmd == GPIOC_INPUT || sub_cmd == GPIOC_READ) {
 		gpio_direction_input(gpio);
 		value = gpio_get_value(gpio);
 	} else {
@@ -233,9 +245,11 @@ static int do_gpio(struct cmd_tbl *cmdtp, int flag, int argc,
 		goto err;
 	} else {
 		printf("%d\n", value);
+		if (sub_cmd == GPIOC_READ)
+			env_set_ulong(str_var, (ulong)value);
 	}
 
-	if (sub_cmd != GPIOC_INPUT && !IS_ERR_VALUE(value)) {
+	if (sub_cmd != GPIOC_INPUT && sub_cmd != GPIOC_READ && !IS_ERR_VALUE(value)) {
 		int nval = gpio_get_value(gpio);
 
 		if (IS_ERR_VALUE(nval)) {
@@ -267,4 +281,6 @@ U_BOOT_CMD(gpio, 4, 0, do_gpio,
 	   "query and control gpio pins",
 	   "<input|set|clear|toggle> <pin>\n"
 	   "    - input/set/clear/toggle the specified pin\n"
+	   "gpio read <name> <pin>\n"
+	   "    - set environment variable 'name' to the specified pin\n"
 	   "gpio status [-a] [<bank> | <pin>]  - show [all/claimed] GPIOs");
diff --git a/test/py/tests/test_gpio.py b/test/py/tests/test_gpio.py
index 8c64f686b0b..52bc8502d3e 100644
--- a/test/py/tests/test_gpio.py
+++ b/test/py/tests/test_gpio.py
@@ -35,3 +35,18 @@ def test_gpio_exit_statuses(u_boot_console):
     assert(expected_response in response)
     response = u_boot_console.run_command('gpio input 200; echo rc:$?')
     assert(expected_response in response)
+
+ at pytest.mark.boardspec('sandbox')
+ at pytest.mark.buildconfigspec('cmd_gpio')
+def test_gpio_read(u_boot_console):
+    """Test that gpio read correctly sets the variable to the value of a gpio pin."""
+
+    response = u_boot_console.run_command('gpio read var 0; echo val:$var')
+    expected_response = 'val:0'
+    assert(expected_response in response)
+    response = u_boot_console.run_command('gpio toggle 0; gpio read var 0; echo val:$var')
+    expected_response = 'val:1'
+    assert(expected_response in response)
+    response = u_boot_console.run_command('setenv var; gpio read var nonexistent-gpio; echo val:$var')
+    expected_response = 'val:'
+    assert(expected_response in response)
-- 
2.34.1



More information about the U-Boot mailing list