[U-Boot] [PATCH v2] sun8i: h3: Support H3 variant of Orange Pi Zero Plus 2

2019-11-19 Thread Diego Rondini
Orangepi Zero Plus 2 is an open-source single-board computer, available
in two Allwinner SOC variants, H3 and H5. We add support for H3 variant
here, as the H5 is already supported.

H3 Orangepi Zero Plus 2 has:
- Quad-core Cortex-A7
- 512MB DDR3
- microSD slot and 8GB eMMC
- Debug TTL UART
- HDMI
- Wifi + BT
- OTG + power supply

Sync dts from linux v5.2 commit:
"ARM: dts: sunxi: h3/h5: Remove stale pinctrl-names entry"
(sha1: 75f9a058838be9880afd75c4cb14e1bf4fe34a0b)
Commit:
"ARM: dts: sun8i: h3: Refactor the pinctrl node names"
(sha1: a4dc791974e568a15f7f37131729b1a6912f4811)
has been avoided as it breaks U-Boot build.

Signed-off-by: Diego Rondini 
---
Changes in v2:
- clarify where the dts comes from
---
 arch/arm/dts/Makefile |   3 +-
 arch/arm/dts/sun8i-h3-orangepi-zero-plus2.dts | 139 ++
 board/sunxi/MAINTAINERS   |   5 +
 configs/orangepi_zero_plus2_h3_defconfig  |  19 +++
 4 files changed, 165 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/dts/sun8i-h3-orangepi-zero-plus2.dts
 create mode 100644 configs/orangepi_zero_plus2_h3_defconfig

diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index d8846df1bd..fc6d66ddab 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -522,7 +522,8 @@ dtb-$(CONFIG_MACH_SUN8I_H3) += \
sun8i-h3-orangepi-pc.dtb \
sun8i-h3-orangepi-pc-plus.dtb \
sun8i-h3-orangepi-plus.dtb \
-   sun8i-h3-orangepi-plus2e.dtb
+   sun8i-h3-orangepi-plus2e.dtb \
+   sun8i-h3-orangepi-zero-plus2.dtb
 dtb-$(CONFIG_MACH_SUN8I_R40) += \
sun8i-r40-bananapi-m2-ultra.dtb \
sun8i-v40-bananapi-m2-berry.dtb
diff --git a/arch/arm/dts/sun8i-h3-orangepi-zero-plus2.dts 
b/arch/arm/dts/sun8i-h3-orangepi-zero-plus2.dts
new file mode 100644
index 00..f2f7b7a925
--- /dev/null
+++ b/arch/arm/dts/sun8i-h3-orangepi-zero-plus2.dts
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2017 Jagan Teki 
+ * Copyright (C) 2018 Diego Rondini 
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "sun8i-h3.dtsi"
+
+#include 
+
+/ {
+   model = "OrangePi Zero Plus2 H3";
+   compatible = "xunlong,orangepi-zero-plus2-h3", "allwinner,sun8i-h3";
+
+   aliases {
+   serial0 = &uart0;
+   };
+
+   chosen {
+   stdout-path = "serial0:115200n8";
+   };
+
+   connector {
+   compatible = "hdmi-connector";
+   type = "a";
+
+   port {
+   hdmi_con_in: endpoint {
+   remote-endpoint = <&hdmi_out_con>;
+   };
+   };
+   };
+
+   reg_vcc3v3: vcc3v3 {
+   compatible = "regulator-fixed";
+   regulator-name = "vcc3v3";
+   regulator-min-microvolt = <330>;
+   regulator-max-microvolt = <330>;
+ 

Re: [PATCH v2] sun8i: h3: Support H3 variant of Orange Pi Zero Plus 2

2019-12-05 Thread Diego Rondini
On Tue, Nov 19, 2019 at 2:47 PM Diego Rondini
 wrote:
>
> Orangepi Zero Plus 2 is an open-source single-board computer, available
> in two Allwinner SOC variants, H3 and H5. We add support for H3 variant
> here, as the H5 is already supported.
>
> H3 Orangepi Zero Plus 2 has:
> - Quad-core Cortex-A7
> - 512MB DDR3
> - microSD slot and 8GB eMMC
> - Debug TTL UART
> - HDMI
> - Wifi + BT
> - OTG + power supply
>
> Sync dts from linux v5.2 commit:
> "ARM: dts: sunxi: h3/h5: Remove stale pinctrl-names entry"
> (sha1: 75f9a058838be9880afd75c4cb14e1bf4fe34a0b)
> Commit:
> "ARM: dts: sun8i: h3: Refactor the pinctrl node names"
> (sha1: a4dc791974e568a15f7f37131729b1a6912f4811)
> has been avoided as it breaks U-Boot build.
>
> Signed-off-by: Diego Rondini 
> ---
> Changes in v2:
> - clarify where the dts comes from
> ---

Hi,

is the commit message ok now?

Diego Rondini


Sourcing a signed boot script

2019-12-05 Thread Diego Rondini
Hi,

I would like to ask if it is possible to source a script after
verifying its signature.

Currently I've been able to source a script from a signed FIT image,
before doing "bootm", with:
source :
But this way the signature is not checked yet, so the script cannot be trusted.

According to the docs[1] it seems that it's not possible yet to verify
a FIT image signature without also booting the corresponding image. Is
that right?


[1] 
https://gitlab.denx.de/u-boot/u-boot/blob/v2019.10/doc/uImage.FIT/signature.txt#L580

Thank you,
Diego Rondini


Re: Sourcing a signed boot script

2019-12-06 Thread Diego Rondini
Hi Lukasz,

On Thu, Dec 5, 2019 at 11:14 PM Lukasz Majewski  wrote:
>
> Hi Diego,
>
> > Hi,
> >
> > I would like to ask if it is possible to source a script after
> > verifying its signature.
> >
> > Currently I've been able to source a script from a signed FIT image,
> > before doing "bootm", with:
> > source :
> > But this way the signature is not checked yet, so the script cannot
> > be trusted.
> >
> > According to the docs[1] it seems that it's not possible yet to verify
> > a FIT image signature without also booting the corresponding image. Is
> > that right?
>
> You can look into the "spl" command, which does the FIT parsing (to
> prepare data for falcon mode booting).
>
> You may want to re-use such "dry-run" feature to verify the signature,
> extract the script and use it.
>
> (And yes, I don't think that checking the signature for script works
> out of the box).
>

I will have a look at your suggestion and report back the outcome!

Thanks again,
Diego Rondini


Re: [U-Boot] How to enable USB Mass Storage

2020-05-22 Thread Diego Rondini
Hi list,


> I want to use the ums command to access the SD card of a
> A20-OlinuxIno-Lime
> board via usb-org cable. For that I start the CPU in FEL mode, download
> the
> u-boot-sunxi-with-spl.bin file by sunxi-fel tool. I do this FEL mode boot
> for
> preparation of an Einstein A20 board, which has only an internal MMC. I
> run on
> uboot serial console:
>
> => ums 0 mmc 0
> UMS: LUN 0, dev 0, hwpart 0, sector 0x0, count 0x1dc000
> Controller uninitialized
> g_dnl_register: failed!, error: -6
> g_dnl_register failed
>

Sorry to jump in such an old thread, but as this is still an issue in
current master (~ 2020.07-rc2) I don't think it hurts.

This error is typically encountered with Allwinner SOCs when:
CONFIG_CMD_USB_MASS_STORAGE=y
but CONFIG_USB_ETHER is not set.

Enabling CONFIG_USB_ETHER=y workarounded the issue for me, as reported also
elsewhere:
http://patchwork.ozlabs.org/project/uboot/patch/caexmxltm9bhx7aaub+mazgbdw2ccsoo3ne6ep7dbm8mmrya...@mail.gmail.com/#1976362
http://linux-sunxi.org/U-Boot/USB_Mass_Storage#Prerequisites

Regards,
Diego Rondini


[U-Boot] [PATCH] sun8i: h3: Support H3 variant of Orange Pi Zero Plus 2

2019-11-06 Thread Diego Rondini
Orangepi Zero Plus 2 is an open-source single-board computer, available
in two Allwinner SOC variants, H3 and H5. We add support for H3 variant
here, as the H5 is already supported.

H3 Orangepi Zero Plus 2 has:
- Quad-core Cortex-A7
- 512MB DDR3
- microSD slot and 8GB eMMC
- Debug TTL UART
- HDMI
- Wifi + BT
- OTG + power supply

Signed-off-by: Diego Rondini 
---
 arch/arm/dts/Makefile |   3 +-
 arch/arm/dts/sun8i-h3-orangepi-zero-plus2.dts | 139 ++
 board/sunxi/MAINTAINERS   |   5 +
 configs/orangepi_zero_plus2_h3_defconfig  |  19 +++
 4 files changed, 165 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/dts/sun8i-h3-orangepi-zero-plus2.dts
 create mode 100644 configs/orangepi_zero_plus2_h3_defconfig

diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 251d32ca62..5c7b8cfcc9 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -513,7 +513,8 @@ dtb-$(CONFIG_MACH_SUN8I_H3) += \
sun8i-h3-orangepi-pc.dtb \
sun8i-h3-orangepi-pc-plus.dtb \
sun8i-h3-orangepi-plus.dtb \
-   sun8i-h3-orangepi-plus2e.dtb
+   sun8i-h3-orangepi-plus2e.dtb \
+   sun8i-h3-orangepi-zero-plus2.dtb
 dtb-$(CONFIG_MACH_SUN8I_R40) += \
sun8i-r40-bananapi-m2-ultra.dtb \
sun8i-v40-bananapi-m2-berry.dtb
diff --git a/arch/arm/dts/sun8i-h3-orangepi-zero-plus2.dts 
b/arch/arm/dts/sun8i-h3-orangepi-zero-plus2.dts
new file mode 100644
index 00..f2f7b7a925
--- /dev/null
+++ b/arch/arm/dts/sun8i-h3-orangepi-zero-plus2.dts
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2017 Jagan Teki 
+ * Copyright (C) 2018 Diego Rondini 
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "sun8i-h3.dtsi"
+
+#include 
+
+/ {
+   model = "OrangePi Zero Plus2 H3";
+   compatible = "xunlong,orangepi-zero-plus2-h3", "allwinner,sun8i-h3";
+
+   aliases {
+   serial0 = &uart0;
+   };
+
+   chosen {
+   stdout-path = "serial0:115200n8";
+   };
+
+   connector {
+   compatible = "hdmi-connector";
+   type = "a";
+
+   port {
+   hdmi_con_in: endpoint {
+   remote-endpoint = <&hdmi_out_con>;
+   };
+   };
+   };
+
+   reg_vcc3v3: vcc3v3 {
+   compatible = "regulator-fixed";
+   regulator-name = "vcc3v3";
+   regulator-min-microvolt = <330>;
+   regulator-max-microvolt = <330>;
+   };
+
+   wifi_pwrseq: wifi_pwrseq {
+   compatible = "mmc-pwrseq-simple";
+   reset-gpios = <&pio 0 9 GPIO_ACTIVE_LOW>; /* PA9 */
+   post-power-on-delay-ms = <200>;
+   };
+};
+
+&de {
+   status = "okay";
+};
+
+&hdmi {
+   status = "okay";
+};
+
+&hdmi_out {
+ 

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

2022-04-11 Thread Diego Rondini
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 
---
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 
 #include 
 #include 
+#ifdef CONFIG_CMD_GPIO_READ
+#include 
+#endif
 #include 
 #include 
 
@@ -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",
   " \n"
   "- input/set/clear/toggle the specified pin\n"
+#ifdef CONFIG_CMD_GPIO_READ
+  "gpio read  \n"
+  "- set environment variable 'name' to the specified pin\n"
+#endif
   "gpio status [-a] [ | ]  - show [all/claimed] GPIOs");
diff --git a/configs/sandbox_defconfig

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

2022-03-22 Thread Diego Rondini
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 
---
 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 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -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",
   " \n"
   "- input/set/clear/toggle the specified pin\n"
+  "gpio read  \n"
+  "- set environment variable 'name' to the specified pin\n"
   "gpio status [-a] [ | ]  - 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)
+
+@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')
+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