From ff52665d03e220ada14e3e02f8d485b48d8c8eaa Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 13 Jan 2020 11:35:14 +0100 Subject: test: dm: update test for pins configuration in gpio Add tests for new API set_dir_flags and set_dir_flags and associated code in gpio uclass. Test support for new flags GPIO_OPEN_DRAIN, GPIO_OPEN_SOURCE GPIO_PULL_UP and GPIO_PULL_DOWN. Reviewed-by: Simon Glass Signed-off-by: Patrick Delaunay --- arch/sandbox/dts/test.dts | 16 ++++++++ arch/sandbox/include/asm/gpio.h | 20 ++++++++++ drivers/gpio/sandbox.c | 86 +++++++++++++++++++++++++++++++---------- test/dm/gpio.c | 66 ++++++++++++++++++++++++++++--- test/dm/test-fdt.c | 2 +- 5 files changed, 163 insertions(+), 27 deletions(-) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index f5f43eb..0b1c29f 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -16,6 +16,7 @@ eth5 = ð_5; gpio1 = &gpio_a; gpio2 = &gpio_b; + gpio3 = &gpio_c; i2c0 = "/i2c@0"; mmc0 = "/mmc0"; mmc1 = "/mmc1"; @@ -97,6 +98,13 @@ <&gpio_b 7 GPIO_IN 3 2 1>, <&gpio_b 8 GPIO_OUT 3 2 1>, <&gpio_b 9 (GPIO_OUT|GPIO_OUT_ACTIVE) 3 2 1>; + test3-gpios = + <&gpio_c 0 (GPIO_OUT|GPIO_OPEN_DRAIN)>, + <&gpio_c 1 (GPIO_OUT|GPIO_OPEN_SOURCE)>, + <&gpio_c 2 GPIO_OUT>, + <&gpio_c 3 (GPIO_IN|GPIO_PULL_UP)>, + <&gpio_c 4 (GPIO_IN|GPIO_PULL_DOWN)>, + <&gpio_c 5 GPIO_IN>; int-value = <1234>; uint-value = <(-1234)>; int64-value = /bits/ 64 <0x1111222233334444>; @@ -307,6 +315,14 @@ sandbox,gpio-count = <10>; }; + gpio_c: extra2-gpios { + compatible = "sandbox,gpio"; + gpio-controller; + #gpio-cells = <2>; + gpio-bank-name = "c"; + sandbox,gpio-count = <10>; + }; + i2c@0 { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h index cfb803b..df4ba4f 100644 --- a/arch/sandbox/include/asm/gpio.h +++ b/arch/sandbox/include/asm/gpio.h @@ -62,4 +62,24 @@ int sandbox_gpio_get_direction(struct udevice *dev, unsigned int offset); int sandbox_gpio_set_direction(struct udevice *dev, unsigned int offset, int output); +/** + * Return the simulated flags of a GPIO (used only in sandbox test code) + * + * @param dev device to use + * @param offset GPIO offset within bank + * @return dir_flags: bitfield accesses by GPIOD_ defines + */ +ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset); + +/** + * Set the simulated flags of a GPIO (used only in sandbox test code) + * + * @param dev device to use + * @param offset GPIO offset within bank + * @param flags dir_flags: bitfield accesses by GPIOD_ defines + * @return -1 on error, 0 if ok + */ +int sandbox_gpio_set_dir_flags(struct udevice *dev, unsigned int offset, + ulong flags); + #endif diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c index c2a8adc..a9c470e 100644 --- a/drivers/gpio/sandbox.c +++ b/drivers/gpio/sandbox.c @@ -8,43 +8,43 @@ #include #include #include +#include #include +#include #include #include -/* Flags for each GPIO */ -#define GPIOF_OUTPUT (1 << 0) /* Currently set as an output */ -#define GPIOF_HIGH (1 << 1) /* Currently set high */ struct gpio_state { const char *label; /* label given by requester */ - u8 flags; /* flags (GPIOF_...) */ + ulong dir_flags; /* dir_flags (GPIOD_...) */ }; -/* Access routines for GPIO state */ -static u8 *get_gpio_flags(struct udevice *dev, unsigned offset) +/* Access routines for GPIO dir flags */ +static ulong *get_gpio_dir_flags(struct udevice *dev, unsigned int offset) { struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); struct gpio_state *state = dev_get_priv(dev); if (offset >= uc_priv->gpio_count) { - static u8 invalid_flags; + static ulong invalid_dir_flags; printf("sandbox_gpio: error: invalid gpio %u\n", offset); - return &invalid_flags; + return &invalid_dir_flags; } - return &state[offset].flags; + return &state[offset].dir_flags; + } -static int get_gpio_flag(struct udevice *dev, unsigned offset, int flag) +static int get_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag) { - return (*get_gpio_flags(dev, offset) & flag) != 0; + return (*get_gpio_dir_flags(dev, offset) & flag) != 0; } -static int set_gpio_flag(struct udevice *dev, unsigned offset, int flag, +static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag, int value) { - u8 *gpio = get_gpio_flags(dev, offset); + ulong *gpio = get_gpio_dir_flags(dev, offset); if (value) *gpio |= flag; @@ -60,24 +60,40 @@ static int set_gpio_flag(struct udevice *dev, unsigned offset, int flag, int sandbox_gpio_get_value(struct udevice *dev, unsigned offset) { - if (get_gpio_flag(dev, offset, GPIOF_OUTPUT)) + if (get_gpio_flag(dev, offset, GPIOD_IS_OUT)) debug("sandbox_gpio: get_value on output gpio %u\n", offset); - return get_gpio_flag(dev, offset, GPIOF_HIGH); + return get_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE); } int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value) { - return set_gpio_flag(dev, offset, GPIOF_HIGH, value); + return set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE, value); } int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset) { - return get_gpio_flag(dev, offset, GPIOF_OUTPUT); + return get_gpio_flag(dev, offset, GPIOD_IS_OUT); } int sandbox_gpio_set_direction(struct udevice *dev, unsigned offset, int output) { - return set_gpio_flag(dev, offset, GPIOF_OUTPUT, output); + set_gpio_flag(dev, offset, GPIOD_IS_OUT, output); + set_gpio_flag(dev, offset, GPIOD_IS_IN, !(output)); + + return 0; +} + +ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset) +{ + return *get_gpio_dir_flags(dev, offset); +} + +int sandbox_gpio_set_dir_flags(struct udevice *dev, unsigned int offset, + ulong flags) +{ + *get_gpio_dir_flags(dev, offset) = flags; + + return 0; } /* @@ -126,9 +142,12 @@ static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value) static int sb_gpio_get_function(struct udevice *dev, unsigned offset) { - if (get_gpio_flag(dev, offset, GPIOF_OUTPUT)) + if (get_gpio_flag(dev, offset, GPIOD_IS_OUT)) return GPIOF_OUTPUT; - return GPIOF_INPUT; + if (get_gpio_flag(dev, offset, GPIOD_IS_IN)) + return GPIOF_INPUT; + + return GPIOF_INPUT; /*GPIO is not configurated */ } static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, @@ -143,14 +162,39 @@ static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, /* sandbox test specific, not defined in gpio.h */ if (args->args[1] & GPIO_IN) desc->flags |= GPIOD_IS_IN; + if (args->args[1] & GPIO_OUT) desc->flags |= GPIOD_IS_OUT; + if (args->args[1] & GPIO_OUT_ACTIVE) desc->flags |= GPIOD_IS_OUT_ACTIVE; return 0; } +static int sb_gpio_set_dir_flags(struct udevice *dev, unsigned int offset, + ulong flags) +{ + ulong *dir_flags; + + debug("%s: offset:%u, dir_flags = %lx\n", __func__, offset, flags); + + dir_flags = get_gpio_dir_flags(dev, offset); + + *dir_flags = flags; + + return 0; +} + +static int sb_gpio_get_dir_flags(struct udevice *dev, unsigned int offset, + ulong *flags) +{ + debug("%s: offset:%u\n", __func__, offset); + *flags = *get_gpio_dir_flags(dev, offset); + + return 0; +} + static const struct dm_gpio_ops gpio_sandbox_ops = { .direction_input = sb_gpio_direction_input, .direction_output = sb_gpio_direction_output, @@ -158,6 +202,8 @@ static const struct dm_gpio_ops gpio_sandbox_ops = { .set_value = sb_gpio_set_value, .get_function = sb_gpio_get_function, .xlate = sb_gpio_xlate, + .set_dir_flags = sb_gpio_set_dir_flags, + .get_dir_flags = sb_gpio_get_dir_flags, }; static int sandbox_gpio_ofdata_to_platdata(struct udevice *dev) diff --git a/test/dm/gpio.c b/test/dm/gpio.c index 2dfb9fd..f5c7aaf 100644 --- a/test/dm/gpio.c +++ b/test/dm/gpio.c @@ -24,9 +24,9 @@ static int dm_test_gpio(struct unit_test_state *uts) char buf[80]; /* - * We expect to get 3 banks. One is anonymous (just numbered) and - * comes from platdata. The other two are named a (20 gpios) - * and b (10 gpios) and come from the device tree. See + * We expect to get 4 banks. One is anonymous (just numbered) and + * comes from platdata. The other are named a (20 gpios), + * b (10 gpios) and c (10 gpios) and come from the device tree. See * test/dm/test.dts. */ ut_assertok(gpio_lookup_name("b4", &dev, &offset, &gpio)); @@ -73,6 +73,18 @@ static int dm_test_gpio(struct unit_test_state *uts) ut_assertok(ops->set_value(dev, offset, 1)); ut_asserteq(1, ops->get_value(dev, offset)); + /* Make it an open drain output, and reset it */ + ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE, + sandbox_gpio_get_dir_flags(dev, offset)); + ut_assertok(ops->set_dir_flags(dev, offset, + GPIOD_IS_OUT | GPIOD_OPEN_DRAIN)); + ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN, + sandbox_gpio_get_dir_flags(dev, offset)); + ut_assertok(ops->set_dir_flags(dev, offset, + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE)); + ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE, + sandbox_gpio_get_dir_flags(dev, offset)); + /* Make it an input */ ut_assertok(ops->direction_input(dev, offset)); ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf))); @@ -208,11 +220,14 @@ static int dm_test_gpio_phandles(struct unit_test_state *uts) desc_list2, ARRAY_SIZE(desc_list2), 0)); + ut_asserteq(GPIOF_INPUT, gpio_get_function(gpio_a, 4, NULL)); ut_assertok(gpio_free_list(dev, desc_list, 3)); + ut_asserteq(GPIOF_UNUSED, gpio_get_function(gpio_a, 4, NULL)); ut_asserteq(3, gpio_request_list_by_name(dev, "test-gpios", desc_list, ARRAY_SIZE(desc_list), GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE)); + ut_asserteq(GPIOF_OUTPUT, gpio_get_function(gpio_a, 4, NULL)); ut_asserteq_ptr(gpio_a, desc_list[0].dev); ut_asserteq(1, desc_list[0].offset); ut_asserteq_ptr(gpio_a, desc_list[1].dev); @@ -222,10 +237,14 @@ static int dm_test_gpio_phandles(struct unit_test_state *uts) ut_asserteq(1, dm_gpio_get_value(desc_list)); ut_assertok(gpio_free_list(dev, desc_list, 3)); + ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE, + sandbox_gpio_get_dir_flags(gpio_a, 1)); ut_asserteq(6, gpio_request_list_by_name(dev, "test2-gpios", desc_list, ARRAY_SIZE(desc_list), 0)); - /* This was set to output previously, so still will be */ - ut_asserteq(GPIOF_OUTPUT, gpio_get_function(gpio_a, 1, NULL)); + + /* This was set to output previously but flags resetted to 0 = INPUT */ + ut_asserteq(0, sandbox_gpio_get_dir_flags(gpio_a, 1)); + ut_asserteq(GPIOF_INPUT, gpio_get_function(gpio_a, 1, NULL)); /* Active low should invert the input value */ ut_asserteq(GPIOF_INPUT, gpio_get_function(gpio_b, 6, NULL)); @@ -237,7 +256,42 @@ static int dm_test_gpio_phandles(struct unit_test_state *uts) ut_asserteq(GPIOF_OUTPUT, gpio_get_function(gpio_b, 9, NULL)); ut_asserteq(1, dm_gpio_get_value(&desc_list[5])); - return 0; } DM_TEST(dm_test_gpio_phandles, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Check the gpio pin configuration get from device tree information */ +static int dm_test_gpio_get_dir_flags(struct unit_test_state *uts) +{ + struct gpio_desc desc_list[6]; + struct udevice *dev; + ulong flags; + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + + ut_asserteq(6, gpio_request_list_by_name(dev, "test3-gpios", desc_list, + ARRAY_SIZE(desc_list), 0)); + + ut_assertok(dm_gpio_get_dir_flags(&desc_list[0], &flags)); + ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN, flags); + + ut_assertok(dm_gpio_get_dir_flags(&desc_list[1], &flags)); + ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE, flags); + + ut_assertok(dm_gpio_get_dir_flags(&desc_list[2], &flags)); + ut_asserteq(GPIOD_IS_OUT, flags); + + ut_assertok(dm_gpio_get_dir_flags(&desc_list[3], &flags)); + ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_UP, flags); + + ut_assertok(dm_gpio_get_dir_flags(&desc_list[4], &flags)); + ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_DOWN, flags); + + ut_assertok(dm_gpio_get_dir_flags(&desc_list[5], &flags)); + ut_asserteq(GPIOD_IS_IN, flags); + + ut_assertok(gpio_free_list(dev, desc_list, 6)); + + return 0; +} +DM_TEST(dm_test_gpio_get_dir_flags, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c index a56275a..1128c42 100644 --- a/test/dm/test-fdt.c +++ b/test/dm/test-fdt.c @@ -286,7 +286,7 @@ static int dm_test_alias_highest_id(struct unit_test_state *uts) ut_asserteq(5, ret); ret = dev_read_alias_highest_id("gpio"); - ut_asserteq(2, ret); + ut_asserteq(3, ret); ret = dev_read_alias_highest_id("pci"); ut_asserteq(2, ret); -- cgit v1.1