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.
CONFIG_CMD_GPIO_READ is used to enable the `gpio read` command.

Signed-off-by: Diego Rondini <diego.rond...@kynetics.com>
---
V2:
- enable only when CONFIG_CMD_GPIO_READ is set
- in test_gpio.py check for return code as well
---
 cmd/Kconfig                |  7 ++++++
 cmd/gpio.c                 | 45 +++++++++++++++++++++++++++++++++++---
 configs/sandbox_defconfig  |  1 +
 test/py/tests/test_gpio.py | 14 ++++++++++++
 4 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/cmd/Kconfig b/cmd/Kconfig
index d3abe3a06b..f580797d2d 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -996,6 +996,13 @@ config CMD_GPIO
        help
          GPIO support.
 
+config CMD_GPIO_READ
+       bool "gpio read - save GPIO value to variable"
+       depends on CMD_GPIO
+       help
+         Enables the 'gpio read' command that saves the value
+         of a GPIO pin to a variable.
+
 config CMD_PWM
        bool "pwm"
        depends on DM_PWM
diff --git a/cmd/gpio.c b/cmd/gpio.c
index 4150024e62..53e9ce666f 100644
--- a/cmd/gpio.c
+++ b/cmd/gpio.c
@@ -12,6 +12,9 @@
 #include <dm.h>
 #include <log.h>
 #include <malloc.h>
+#ifdef CONFIG_CMD_GPIO_READ
+#include <env.h>
+#endif
 #include <asm/gpio.h>
 #include <linux/err.h>
 
@@ -25,6 +28,9 @@ enum gpio_cmd {
        GPIOC_SET,
        GPIOC_CLEAR,
        GPIOC_TOGGLE,
+#ifdef CONFIG_CMD_GPIO_READ
+       GPIOC_READ,
+#endif
 };
 
 #if defined(CONFIG_DM_GPIO) && !defined(gpio_status)
@@ -125,6 +131,9 @@ static int do_gpio(struct cmd_tbl *cmdtp, int flag, int 
argc,
        enum gpio_cmd sub_cmd;
        int value;
        const char *str_cmd, *str_gpio = NULL;
+#ifdef CONFIG_CMD_GPIO_READ
+       const char *str_var = NULL;
+#endif
        int ret;
 #ifdef CONFIG_DM_GPIO
        bool all = false;
@@ -137,11 +146,20 @@ 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
+#ifdef CONFIG_CMD_GPIO_READ
+       if (argc > 0 && !strncmp(str_cmd, "read", 2)) {
+               if (argc < 2)
+                       goto show_usage;
+               str_var = *argv;
+               argc--;
+               argv++;
+       }
 #endif
        if (argc > 0)
                str_gpio = *argv;
@@ -174,6 +192,11 @@ static int do_gpio(struct cmd_tbl *cmdtp, int flag, int 
argc,
        case 't':
                sub_cmd = GPIOC_TOGGLE;
                break;
+#ifdef CONFIG_CMD_GPIO_READ
+       case 'r':
+               sub_cmd = GPIOC_READ;
+               break;
+#endif
        default:
                goto show_usage;
        }
@@ -205,7 +228,11 @@ 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
+#ifdef CONFIG_CMD_GPIO_READ
+                       || sub_cmd == GPIOC_READ
+#endif
+                       ) {
                gpio_direction_input(gpio);
                value = gpio_get_value(gpio);
        } else {
@@ -233,9 +260,17 @@ static int do_gpio(struct cmd_tbl *cmdtp, int flag, int 
argc,
                goto err;
        } else {
                printf("%d\n", value);
+#ifdef CONFIG_CMD_GPIO_READ
+               if (sub_cmd == GPIOC_READ)
+                       env_set_ulong(str_var, (ulong)value);
+#endif
        }
 
-       if (sub_cmd != GPIOC_INPUT && !IS_ERR_VALUE(value)) {
+       if (sub_cmd != GPIOC_INPUT && !IS_ERR_VALUE(value)
+#ifdef CONFIG_CMD_GPIO_READ
+                       && sub_cmd != GPIOC_READ
+#endif
+                       ) {
                int nval = gpio_get_value(gpio);
 
                if (IS_ERR_VALUE(nval)) {
@@ -267,4 +302,8 @@ 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"
+#ifdef CONFIG_CMD_GPIO_READ
+          "gpio read <name> <pin>\n"
+          "    - set environment variable 'name' to the specified pin\n"
+#endif
           "gpio status [-a] [<bank> | <pin>]  - show [all/claimed] GPIOs");
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index cb8d590eb6..a65527003d 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -61,6 +61,7 @@ CONFIG_CMD_UNZIP=y
 CONFIG_CMD_BIND=y
 CONFIG_CMD_DEMO=y
 CONFIG_CMD_GPIO=y
+CONFIG_CMD_GPIO_READ=y
 CONFIG_CMD_PWM=y
 CONFIG_CMD_GPT=y
 CONFIG_CMD_GPT_RENAME=y
diff --git a/test/py/tests/test_gpio.py b/test/py/tests/test_gpio.py
index 109649e2c7..fa0af5f82b 100644
--- a/test/py/tests/test_gpio.py
+++ b/test/py/tests/test_gpio.py
@@ -46,6 +46,20 @@ def test_gpio_exit_statuses(u_boot_console):
     response = u_boot_console.run_command('gpio input 200; echo rc:$?')
     assert(expected_response in response)
 
+@pytest.mark.boardspec('sandbox')
+@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,rc:$?')
+    expected_response = 'val:0,rc:0'
+    assert(expected_response in response)
+    response = u_boot_console.run_command('gpio toggle 0; gpio read var 0; 
echo val:$var,rc:$?')
+    expected_response = 'val:1,rc:0'
+    assert(expected_response in response)
+    response = u_boot_console.run_command('setenv var; gpio read var 
nonexistent-gpio; echo val:$var,rc:$?')
+    expected_response = 'val:,rc:1'
+    assert(expected_response in response)
 
 """
 Generic Tests for 'gpio' command on sandbox and real hardware.
-- 
2.34.1

Reply via email to