From: Jean-Jacques Hiblot <jjhib...@ti.com>

Add a test to verify that GPIOs can be acquired/released using the managed
API. Also check that the GPIOs are released when the consumer device is
removed.

Signed-off-by: Jean-Jacques Hiblot <jjhib...@ti.com>
Reviewed-by: Simon Glass <s...@chromium.org>
Signed-off-by: Pratyush Yadav <p.ya...@ti.com>
---

Notes:
    Changes in v5:
    
    - Add Simon's Reviewed-by.
    
    Changes in v4:
    
    - Fix merge conflicts.
    
    - Move "another-test" node down the order to make sure
      dm_test_fdt_uclass_seq() continues to work.
    
    - Bump num_devices to 9 in dm_test_bus_children(), dm_test_fdt(), and
      dm_test_uclass_foreach() to fix broken tests.
    - s/DM_TESTF/UT_TESTF/g

 arch/sandbox/dts/test.dts |  10 ++++
 test/dm/bus.c             |   2 +-
 test/dm/gpio.c            | 102 ++++++++++++++++++++++++++++++++++++++
 test/dm/test-fdt.c        |   6 +--
 4 files changed, 116 insertions(+), 4 deletions(-)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 9f45c48e4e..d35aa6d1f5 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -121,6 +121,9 @@
                        <&gpio_c 5 GPIO_IN>,
                        <&gpio_c 6 (GPIO_ACTIVE_LOW|GPIO_OUT|GPIO_OPEN_DRAIN)>,
                        <&gpio_c 7 (GPIO_ACTIVE_LOW|GPIO_OUT|GPIO_OPEN_SOURCE)>;
+               test4-gpios = <&gpio_a 14>, <&gpio_b 4 1 3 2 1>;
+               test5-gpios = <&gpio_a 19>;
+
                int-value = <1234>;
                uint-value = <(-1234)>;
                int64-value = /bits/ 64 <0x1111222233334444>;
@@ -270,6 +273,13 @@
                compatible = "denx,u-boot-devres-test";
        };
 
+       another-test {
+               reg = <0 2>;
+               compatible = "denx,u-boot-fdt-test";
+               test4-gpios = <&gpio_a 14>, <&gpio_b 4 1 3 2 1>;
+               test5-gpios = <&gpio_a 19>;
+       };
+
        acpi_test1: acpi-test {
                compatible = "denx,u-boot-acpi-test";
                acpi-ssdt-test-data = "ab";
diff --git a/test/dm/bus.c b/test/dm/bus.c
index 865e8bd9fb..27b7266645 100644
--- a/test/dm/bus.c
+++ b/test/dm/bus.c
@@ -120,7 +120,7 @@ UCLASS_DRIVER(testbus) = {
 /* Test that we can probe for children */
 static int dm_test_bus_children(struct unit_test_state *uts)
 {
-       int num_devices = 8;
+       int num_devices = 9;
        struct udevice *bus;
        struct uclass *uc;
 
diff --git a/test/dm/gpio.c b/test/dm/gpio.c
index 4848152644..54e960b185 100644
--- a/test/dm/gpio.c
+++ b/test/dm/gpio.c
@@ -10,6 +10,7 @@
 #include <malloc.h>
 #include <acpi/acpi_device.h>
 #include <asm/gpio.h>
+#include <dm/device-internal.h>
 #include <dm/root.h>
 #include <dm/test.h>
 #include <dm/util.h>
@@ -480,3 +481,104 @@ static int dm_test_gpio_get_acpi_irq(struct 
unit_test_state *uts)
        return 0;
 }
 DM_TEST(dm_test_gpio_get_acpi_irq, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+/* Test that we can get/release GPIOs using managed API */
+static int dm_test_gpio_devm(struct unit_test_state *uts)
+{
+       static const u32 flags = GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE;
+       struct gpio_desc *desc1, *desc2, *desc3, *desc_err;
+       struct udevice *dev;
+       struct udevice *dev2;
+
+       ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "a-test",
+                                             &dev));
+       ut_assertok(uclass_get_device_by_name(UCLASS_TEST_FDT, "another-test",
+                                             &dev2));
+
+       /* Get 3 GPIOs from 'a-test' dev */
+       desc1 = devm_gpiod_get_index(dev, "test4", 0, flags);
+       ut_assert(!IS_ERR(desc1));
+       desc2 = devm_gpiod_get_index(dev, "test4", 1, flags);
+       ut_assert(!IS_ERR(desc2));
+       desc3 = devm_gpiod_get_index_optional(dev, "test5", 0, flags);
+       ut_assert(!IS_ERR(desc3));
+       ut_assert(desc3);
+
+       /*
+        * Try get the same 3 GPIOs from 'a-test' and 'another-test' devices.
+        * check that it fails
+        */
+       desc_err = devm_gpiod_get_index(dev, "test4", 0, flags);
+       ut_asserteq(-EBUSY, PTR_ERR(desc_err));
+       desc_err = devm_gpiod_get_index(dev2, "test4", 0, flags);
+       ut_asserteq(-EBUSY, PTR_ERR(desc_err));
+       desc_err = devm_gpiod_get_index(dev, "test4", 1, flags);
+       ut_asserteq(-EBUSY, PTR_ERR(desc_err));
+       desc_err = devm_gpiod_get_index(dev2, "test4", 1, flags);
+       ut_asserteq(-EBUSY, PTR_ERR(desc_err));
+       desc_err = devm_gpiod_get_index_optional(dev, "test5", 0, flags);
+       ut_asserteq_ptr(NULL, desc_err);
+       desc_err = devm_gpiod_get_index_optional(dev2, "test5", 0, flags);
+       ut_asserteq_ptr(NULL, desc_err);
+
+       /* Try get GPIOs outside of the list */
+       desc_err = devm_gpiod_get_index(dev, "test4", 2, flags);
+       ut_assert(IS_ERR(desc_err));
+       desc_err = devm_gpiod_get_index_optional(dev, "test5", 1, flags);
+       ut_asserteq_ptr(NULL, desc_err);
+
+       /* Manipulate the GPIOs */
+       ut_assertok(dm_gpio_set_value(desc1, 1));
+       ut_asserteq(1, dm_gpio_get_value(desc1));
+       ut_assertok(dm_gpio_set_value(desc1, 0));
+       ut_asserteq(0, dm_gpio_get_value(desc1));
+
+       ut_assertok(dm_gpio_set_value(desc2, 1));
+       ut_asserteq(1, dm_gpio_get_value(desc2));
+       ut_assertok(dm_gpio_set_value(desc2, 0));
+       ut_asserteq(0, dm_gpio_get_value(desc2));
+
+       ut_assertok(dm_gpio_set_value(desc3, 1));
+       ut_asserteq(1, dm_gpio_get_value(desc3));
+       ut_assertok(dm_gpio_set_value(desc3, 0));
+       ut_asserteq(0, dm_gpio_get_value(desc3));
+
+       /* Check that the GPIO cannot be owned by more than one device */
+       desc_err = devm_gpiod_get_index(dev2, "test4", 0, flags);
+       ut_asserteq(-EBUSY, PTR_ERR(desc_err));
+       desc_err = devm_gpiod_get_index(dev2, "test4", 1, flags);
+       ut_asserteq(-EBUSY, PTR_ERR(desc_err));
+       desc_err = devm_gpiod_get_index_optional(dev2, "test5", 0, flags);
+       ut_asserteq_ptr(NULL, desc_err);
+
+       /*
+        * Release one GPIO and check that we can get it back using
+        * 'another-test' and then 'a-test'
+        */
+       devm_gpiod_put(dev, desc2);
+       desc2 = devm_gpiod_get_index(dev2, "test4", 1, flags);
+       ut_assert(!IS_ERR(desc2));
+
+       devm_gpiod_put(dev2, desc2);
+       desc2 = devm_gpiod_get_index(dev, "test4", 1, flags);
+       ut_assert(!IS_ERR(desc2));
+
+       /* Release one GPIO before removing the 'a-test' dev. */
+       devm_gpiod_put(dev, desc2);
+       device_remove(dev, DM_REMOVE_NORMAL);
+
+       /* All the GPIOs must have been freed. We should be able to claim
+        * them with the 'another-test' device.
+        */
+       desc1 = devm_gpiod_get_index(dev2, "test4", 0, flags);
+       ut_assert(!IS_ERR(desc1));
+       desc2 = devm_gpiod_get_index(dev2, "test4", 1, flags);
+       ut_assert(!IS_ERR(desc2));
+       desc3 = devm_gpiod_get_index_optional(dev2, "test5", 0, flags);
+       ut_assert(!IS_ERR(desc3));
+       ut_assert(desc3);
+
+       device_remove(dev2, DM_REMOVE_NORMAL);
+       return 0;
+}
+DM_TEST(dm_test_gpio_devm, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c
index 04802deb7f..26d57f40d1 100644
--- a/test/dm/test-fdt.c
+++ b/test/dm/test-fdt.c
@@ -251,7 +251,7 @@ int dm_check_devices(struct unit_test_state *uts, int 
num_devices)
 /* Test that FDT-based binding works correctly */
 static int dm_test_fdt(struct unit_test_state *uts)
 {
-       const int num_devices = 8;
+       const int num_devices = 9;
        struct udevice *dev;
        struct uclass *uc;
        int ret;
@@ -473,12 +473,12 @@ static int dm_test_uclass_foreach(struct unit_test_state 
*uts)
        count = 0;
        uclass_id_foreach_dev(UCLASS_TEST_FDT, dev, uc)
                count++;
-       ut_asserteq(8, count);
+       ut_asserteq(9, count);
 
        count = 0;
        uclass_foreach_dev(dev, uc)
                count++;
-       ut_asserteq(8, count);
+       ut_asserteq(9, count);
 
        return 0;
 }
-- 
2.28.0

Reply via email to