From 277a0ad8f559e6b54c0d32512697debc659d9fd5 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 13 Jan 2020 11:34:59 +0100 Subject: gpio: remove GPIOD_REQUESTED Remove the define GPIOD_REQUESTED as it is never used and use BIT() macro for other defines. Signed-off-by: Patrick Delaunay Reviewed-by: Simon Glass --- include/asm-generic/gpio.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'include/asm-generic') diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 05777e6afe0..4064efeb8d0 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -117,11 +117,10 @@ struct udevice; struct gpio_desc { struct udevice *dev; /* Device, NULL for invalid GPIO */ unsigned long flags; -#define GPIOD_REQUESTED (1 << 0) /* Requested/claimed */ -#define GPIOD_IS_OUT (1 << 1) /* GPIO is an output */ -#define GPIOD_IS_IN (1 << 2) /* GPIO is an input */ -#define GPIOD_ACTIVE_LOW (1 << 3) /* value has active low */ -#define GPIOD_IS_OUT_ACTIVE (1 << 4) /* set output active */ +#define GPIOD_IS_OUT BIT(1) /* GPIO is an output */ +#define GPIOD_IS_IN BIT(2) /* GPIO is an input */ +#define GPIOD_ACTIVE_LOW BIT(3) /* value has active low */ +#define GPIOD_IS_OUT_ACTIVE BIT(4) /* set output active */ uint offset; /* GPIO offset within the device */ /* -- cgit v1.3.1 From e3f3a121d8ebe15da868be8afbfb3e2a9ff80d4d Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 13 Jan 2020 11:35:00 +0100 Subject: gpio: remove the open_drain API and ops This patch removes the ops get_open_drain/set_open_drain and the API dm_gpio_get_open_drain/dm_gpio_set_open_drain. The ops only provided in one driver (mpc8xxx gpio) and the associated API is never called in boards. This patch prepare a more generic set/get_dir_flags ops, including the open drain property. Reviewed-by: Simon Glass Signed-off-by: Patrick Delaunay --- arch/sandbox/include/asm/gpio.h | 20 -------------------- drivers/gpio/gpio-uclass.c | 36 ------------------------------------ drivers/gpio/mpc8xxx_gpio.c | 22 ---------------------- drivers/gpio/sandbox.c | 35 ----------------------------------- include/asm-generic/gpio.h | 34 ---------------------------------- test/dm/gpio.c | 7 ------- 6 files changed, 154 deletions(-) (limited to 'include/asm-generic') diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h index de8ac37f426..cfb803bb3bb 100644 --- a/arch/sandbox/include/asm/gpio.h +++ b/arch/sandbox/include/asm/gpio.h @@ -42,26 +42,6 @@ int sandbox_gpio_get_value(struct udevice *dev, unsigned int offset); */ int sandbox_gpio_set_value(struct udevice *dev, unsigned int offset, int value); -/** - * Set or reset the simulated open drain mode of a GPIO (used only in sandbox - * test code) - * - * @param gp GPIO number - * @param value value to set (0 for enabled open drain mode, non-zero for - * disabled) - * @return -1 on error, 0 if ok - */ -int sandbox_gpio_set_open_drain(struct udevice *dev, unsigned offset, int value); - -/** - * Return the state of the simulated open drain mode of a GPIO (used only in - * sandbox test code) - * - * @param gp GPIO number - * @return -1 on error, 0 if GPIO is input, >0 if output - */ -int sandbox_gpio_get_open_drain(struct udevice *dev, unsigned offset); - /** * Return the simulated direction of a GPIO (used only in sandbox test code) * diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 0a22441d38a..2515df4e7c7 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -491,38 +491,6 @@ int dm_gpio_set_value(const struct gpio_desc *desc, int value) return 0; } -int dm_gpio_get_open_drain(struct gpio_desc *desc) -{ - struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); - int ret; - - ret = check_reserved(desc, "get_open_drain"); - if (ret) - return ret; - - if (ops->set_open_drain) - return ops->get_open_drain(desc->dev, desc->offset); - else - return -ENOSYS; -} - -int dm_gpio_set_open_drain(struct gpio_desc *desc, int value) -{ - struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); - int ret; - - ret = check_reserved(desc, "set_open_drain"); - if (ret) - return ret; - - if (ops->set_open_drain) - ret = ops->set_open_drain(desc->dev, desc->offset, value); - else - return 0; /* feature not supported -> ignore setting */ - - return ret; -} - int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) { struct udevice *dev = desc->dev; @@ -1053,10 +1021,6 @@ static int gpio_post_bind(struct udevice *dev) ops->get_value += gd->reloc_off; if (ops->set_value) ops->set_value += gd->reloc_off; - if (ops->get_open_drain) - ops->get_open_drain += gd->reloc_off; - if (ops->set_open_drain) - ops->set_open_drain += gd->reloc_off; if (ops->get_function) ops->get_function += gd->reloc_off; if (ops->xlate) diff --git a/drivers/gpio/mpc8xxx_gpio.c b/drivers/gpio/mpc8xxx_gpio.c index 4b385b8b395..1dfd22522c7 100644 --- a/drivers/gpio/mpc8xxx_gpio.c +++ b/drivers/gpio/mpc8xxx_gpio.c @@ -133,26 +133,6 @@ static int mpc8xxx_gpio_get_value(struct udevice *dev, uint gpio) return !!mpc8xxx_gpio_get_val(data->base, gpio_mask(gpio)); } -static int mpc8xxx_gpio_get_open_drain(struct udevice *dev, uint gpio) -{ - struct mpc8xxx_gpio_data *data = dev_get_priv(dev); - - return !!mpc8xxx_gpio_open_drain_val(data->base, gpio_mask(gpio)); -} - -static int mpc8xxx_gpio_set_open_drain(struct udevice *dev, uint gpio, - int value) -{ - struct mpc8xxx_gpio_data *data = dev_get_priv(dev); - - if (value) - mpc8xxx_gpio_open_drain_on(data->base, gpio_mask(gpio)); - else - mpc8xxx_gpio_open_drain_off(data->base, gpio_mask(gpio)); - - return 0; -} - static int mpc8xxx_gpio_get_function(struct udevice *dev, uint gpio) { struct mpc8xxx_gpio_data *data = dev_get_priv(dev); @@ -229,8 +209,6 @@ static const struct dm_gpio_ops gpio_mpc8xxx_ops = { .direction_output = mpc8xxx_gpio_direction_output, .get_value = mpc8xxx_gpio_get_value, .set_value = mpc8xxx_gpio_set_value, - .get_open_drain = mpc8xxx_gpio_get_open_drain, - .set_open_drain = mpc8xxx_gpio_set_open_drain, .get_function = mpc8xxx_gpio_get_function, }; diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c index 2ef5c67ad59..91e8e0677ea 100644 --- a/drivers/gpio/sandbox.c +++ b/drivers/gpio/sandbox.c @@ -14,7 +14,6 @@ /* Flags for each GPIO */ #define GPIOF_OUTPUT (1 << 0) /* Currently set as an output */ #define GPIOF_HIGH (1 << 1) /* Currently set high */ -#define GPIOF_ODR (1 << 2) /* Currently set to open drain mode */ struct gpio_state { const char *label; /* label given by requester */ @@ -70,16 +69,6 @@ int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value) return set_gpio_flag(dev, offset, GPIOF_HIGH, value); } -int sandbox_gpio_get_open_drain(struct udevice *dev, unsigned offset) -{ - return get_gpio_flag(dev, offset, GPIOF_ODR); -} - -int sandbox_gpio_set_open_drain(struct udevice *dev, unsigned offset, int value) -{ - return set_gpio_flag(dev, offset, GPIOF_ODR, value); -} - int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset) { return get_gpio_flag(dev, offset, GPIOF_OUTPUT); @@ -134,28 +123,6 @@ static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value) return sandbox_gpio_set_value(dev, offset, value); } -/* read GPIO ODR value of port 'offset' */ -static int sb_gpio_get_open_drain(struct udevice *dev, unsigned offset) -{ - debug("%s: offset:%u\n", __func__, offset); - - return sandbox_gpio_get_open_drain(dev, offset); -} - -/* write GPIO ODR value to port 'offset' */ -static int sb_gpio_set_open_drain(struct udevice *dev, unsigned offset, int value) -{ - debug("%s: offset:%u, value = %d\n", __func__, offset, value); - - if (!sandbox_gpio_get_direction(dev, offset)) { - printf("sandbox_gpio: error: set_open_drain on input gpio %u\n", - offset); - return -1; - } - - return sandbox_gpio_set_open_drain(dev, offset, value); -} - static int sb_gpio_get_function(struct udevice *dev, unsigned offset) { if (get_gpio_flag(dev, offset, GPIOF_OUTPUT)) @@ -186,8 +153,6 @@ static const struct dm_gpio_ops gpio_sandbox_ops = { .direction_output = sb_gpio_direction_output, .get_value = sb_gpio_get_value, .set_value = sb_gpio_set_value, - .get_open_drain = sb_gpio_get_open_drain, - .set_open_drain = sb_gpio_set_open_drain, .get_function = sb_gpio_get_function, .xlate = sb_gpio_xlate, }; diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 4064efeb8d0..4d5348d8c8e 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -253,8 +253,6 @@ struct dm_gpio_ops { int value); int (*get_value)(struct udevice *dev, unsigned offset); int (*set_value)(struct udevice *dev, unsigned offset, int value); - int (*get_open_drain)(struct udevice *dev, unsigned offset); - int (*set_open_drain)(struct udevice *dev, unsigned offset, int value); /** * get_function() Get the GPIO function * @@ -585,38 +583,6 @@ int dm_gpio_get_value(const struct gpio_desc *desc); int dm_gpio_set_value(const struct gpio_desc *desc, int value); -/** - * dm_gpio_get_open_drain() - Check if open-drain-mode of a GPIO is active - * - * This checks if open-drain-mode for a GPIO is enabled or not. This method is - * optional. - * - * @desc: GPIO description containing device, offset and flags, - * previously returned by gpio_request_by_name() - * @return Value of open drain mode for GPIO (0 for inactive, 1 for active) or - * -ve on error - */ -int dm_gpio_get_open_drain(struct gpio_desc *desc); - -/** - * dm_gpio_set_open_drain() - Switch open-drain-mode of a GPIO on or off - * - * This enables or disables open-drain mode for a GPIO. This method is - * optional; if the driver does not support it, nothing happens when the method - * is called. - * - * In open-drain mode, instead of actively driving the output (Push-pull - * output), the GPIO's pin is connected to the collector (for a NPN transistor) - * or the drain (for a MOSFET) of a transistor, respectively. The pin then - * either forms an open circuit or a connection to ground, depending on the - * state of the transistor. - * - * @desc: GPIO description containing device, offset and flags, - * previously returned by gpio_request_by_name() - * @return 0 if OK, -ve on error - */ -int dm_gpio_set_open_drain(struct gpio_desc *desc, int value); - /** * dm_gpio_set_dir() - Set the direction for a GPIO * diff --git a/test/dm/gpio.c b/test/dm/gpio.c index 349123a657c..2dfb9fd4306 100644 --- a/test/dm/gpio.c +++ b/test/dm/gpio.c @@ -73,13 +73,6 @@ 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(0, sandbox_gpio_get_open_drain(dev, offset)); - ut_assertok(ops->set_open_drain(dev, offset, 1)); - ut_asserteq(1, sandbox_gpio_get_open_drain(dev, offset)); - ut_assertok(ops->set_open_drain(dev, offset, 0)); - ut_asserteq(0, sandbox_gpio_get_open_drain(dev, offset)); - /* Make it an input */ ut_assertok(ops->direction_input(dev, offset)); ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf))); -- cgit v1.3.1 From 9360bb06f1db4597b7d08ea95b48a17025a97618 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 13 Jan 2020 11:35:05 +0100 Subject: gpio: add helper GPIOD_FLAGS_OUTPUT Add a macro to provide the GPIO output value according the dir flags content. Signed-off-by: Patrick Delaunay Reviewed-by: Simon Glass --- drivers/gpio/gpio-uclass.c | 9 +++------ include/asm-generic/gpio.h | 6 ++++++ 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'include/asm-generic') diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index b5cebfdbc6a..29c8c0f57bb 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -542,12 +542,9 @@ static int _dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) } if (flags & GPIOD_IS_OUT) { - int value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0; - - if (flags & GPIOD_ACTIVE_LOW) - value = !value; - ret = ops->direction_output(dev, desc->offset, value); - } else if (flags & GPIOD_IS_IN) { + ret = ops->direction_output(dev, desc->offset, + GPIOD_FLAGS_OUTPUT(flags)); + } else if (flags & GPIOD_IS_IN) { ret = ops->direction_input(dev, desc->offset); } diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 4d5348d8c8e..5686df7cece 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -129,6 +129,12 @@ struct gpio_desc { */ }; +/* helper to compute the value of the gpio output */ +#define GPIOD_FLAGS_OUTPUT_MASK (GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE) +#define GPIOD_FLAGS_OUTPUT(flags) \ + (((((flags) & GPIOD_FLAGS_OUTPUT_MASK) == GPIOD_IS_OUT_ACTIVE) || \ + (((flags) & GPIOD_FLAGS_OUTPUT_MASK) == GPIOD_ACTIVE_LOW))) + /** * dm_gpio_is_valid() - Check if a GPIO is valid * -- cgit v1.3.1 From 695e5fd5469ab052126c4cb30c4d26e6058de067 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 13 Jan 2020 11:35:06 +0100 Subject: gpio: update dir_flags management Update the flag management in GPIO uclass: the desc->flags is always combined with the requested flags and the GPIO descriptor is updated for further call. Add a function dm_gpio_get_dir_flags to get dynamically the current dir_flags (configuration and value). This patch prepare introduction of the dir flags support with new ops. Signed-off-by: Patrick Delaunay Reviewed-by: Simon Glass --- drivers/gpio/gpio-uclass.c | 27 +++++++++++++++++++++++++-- include/asm-generic/gpio.h | 22 ++++++++++++++++------ 2 files changed, 41 insertions(+), 8 deletions(-) (limited to 'include/asm-generic') diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 29c8c0f57bb..9550e45e6cd 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -141,8 +141,9 @@ int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc, if (args->args_count < 2) return 0; + desc->flags = 0; if (args->args[1] & GPIO_ACTIVE_LOW) - desc->flags = GPIOD_ACTIVE_LOW; + desc->flags |= GPIOD_ACTIVE_LOW; return 0; } @@ -559,6 +560,8 @@ int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) if (ret) return ret; + /* combine the requested flags (for IN/OUT) and the descriptor flags */ + flags |= desc->flags; ret = _dm_gpio_set_dir_flags(desc, flags); /* update the descriptor flags */ @@ -579,6 +582,26 @@ int dm_gpio_set_dir(struct gpio_desc *desc) return _dm_gpio_set_dir_flags(desc, desc->flags); } +int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags) +{ + int ret; + ulong dir_flags; + + ret = check_reserved(desc, "get_dir_flags"); + if (ret) + return ret; + + dir_flags = desc->flags; + /* only GPIOD_IS_OUT_ACTIVE is provided by uclass */ + dir_flags &= ~GPIOD_IS_OUT_ACTIVE; + if ((desc->flags & GPIOD_IS_OUT) && _gpio_get_value(desc)) + dir_flags |= GPIOD_IS_OUT_ACTIVE; + + *flags = dir_flags; + + return 0; +} + /** * gpio_get_value() - [COMPAT] Sample GPIO pin and return it's value * gpio: GPIO number @@ -849,7 +872,7 @@ static int gpio_request_tail(int ret, const char *nodename, debug("%s: dm_gpio_requestf failed\n", __func__); goto err; } - ret = dm_gpio_set_dir_flags(desc, flags | desc->flags); + ret = dm_gpio_set_dir_flags(desc, flags); if (ret) { debug("%s: dm_gpio_set_dir failed\n", __func__); goto err; diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 5686df7cece..1329d02f873 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -592,8 +592,7 @@ int dm_gpio_set_value(const struct gpio_desc *desc, int value); /** * dm_gpio_set_dir() - Set the direction for a GPIO * - * This sets up the direction according tot the provided flags. It will do - * nothing unless the direction is actually specified. + * This sets up the direction according to the GPIO flags: desc->flags. * * @desc: GPIO description containing device, offset and flags, * previously returned by gpio_request_by_name() @@ -602,11 +601,10 @@ int dm_gpio_set_value(const struct gpio_desc *desc, int value); int dm_gpio_set_dir(struct gpio_desc *desc); /** - * dm_gpio_set_dir_flags() - Set direction using specific flags + * dm_gpio_set_dir_flags() - Set direction using description and added flags * - * This is like dm_gpio_set_dir() except that the flags value is provided - * instead of being used from desc->flags. This is needed because in many - * cases the GPIO description does not include direction information. + * This sets up the direction according to the provided flags and the GPIO + * description (desc->flags) which include direction information. * Note that desc->flags is updated by this function. * * @desc: GPIO description containing device, offset and flags, @@ -616,6 +614,18 @@ int dm_gpio_set_dir(struct gpio_desc *desc); */ int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags); +/** + * dm_gpio_get_dir_flags() - Get direction flags + * + * read the current direction flags + * + * @desc: GPIO description containing device, offset and flags, + * previously returned by gpio_request_by_name() + * @flags: place to put the used flags + * @return 0 if OK, -ve on error, in which case desc->flags is not updated + */ +int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags); + /** * gpio_get_number() - Get the global GPIO number of a GPIO * -- cgit v1.3.1 From 477ca57b9a53120a14bdca356612fce15211345d Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 13 Jan 2020 11:35:07 +0100 Subject: gpio: add support of new GPIO direction flag This commit manages the new dir flags that can be used in gpio specifiers to indicate the pull-up or pull-down resistor configuration for output gpio (GPIO_PULL_UP, GPIO_PULL_DOWN) or the Open Drain/Open Source configuration for input gpio (GPIO_OPEN_DRAIN, GPIO_OPEN_SOURCE). These flags are already supported in Linux kernel in gpio lib. This patch only parse and save the direction flags in GPIO descriptor (desc->flags), it prepares the introduction of new ops to manage them. The GPIO uclass supports new GPIO flags from device-tree (GPIO_XXX define in include/dt-bindings/gpio/gpio.h) and translate them in the dir flags (GPIOD_XXX): - GPIO_PULL_UP => GPIOD_PULL_UP - GPIO_PULL_DOWN => GPIOD_PULL_DOWN - GPIO_OPEN_DRAIN => GPIOD_OPEN_DRAIN - GPIO_OPEN_SOURCE => GPIOD_OPEN_SOURCE This patch also adds protection in the check_dir_flags function for new invalid configuration of the dir flags. Signed-off-by: Patrick Delaunay Reviewed-by: Simon Glass --- drivers/gpio/gpio-uclass.c | 30 ++++++++++++++++++++++++++++++ include/asm-generic/gpio.h | 6 +++++- 2 files changed, 35 insertions(+), 1 deletion(-) (limited to 'include/asm-generic') diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 9550e45e6cd..25263994d24 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -145,6 +145,24 @@ int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc, if (args->args[1] & GPIO_ACTIVE_LOW) desc->flags |= GPIOD_ACTIVE_LOW; + /* + * need to test 2 bits for gpio output binding: + * OPEN_DRAIN (0x6) = SINGLE_ENDED (0x2) | LINE_OPEN_DRAIN (0x4) + * OPEN_SOURCE (0x2) = SINGLE_ENDED (0x2) | LINE_OPEN_SOURCE (0x0) + */ + if (args->args[1] & GPIO_SINGLE_ENDED) { + if (args->args[1] & GPIO_LINE_OPEN_DRAIN) + desc->flags |= GPIOD_OPEN_DRAIN; + else + desc->flags |= GPIOD_OPEN_SOURCE; + } + + if (args->args[1] & GPIO_PULL_UP) + desc->flags |= GPIOD_PULL_UP; + + if (args->args[1] & GPIO_PULL_DOWN) + desc->flags |= GPIOD_PULL_DOWN; + return 0; } @@ -521,6 +539,18 @@ static int check_dir_flags(ulong flags) return -EINVAL; } + if ((flags & GPIOD_PULL_UP) && (flags & GPIOD_PULL_DOWN)) { + log_debug("%s: flags 0x%lx has GPIOD_PULL_UP and GPIOD_PULL_DOWN\n", + __func__, flags); + return -EINVAL; + } + + if ((flags & GPIOD_OPEN_DRAIN) && (flags & GPIOD_OPEN_SOURCE)) { + log_debug("%s: flags 0x%lx has GPIOD_OPEN_DRAIN and GPIOD_OPEN_SOURCE\n", + __func__, flags); + return -EINVAL; + } + return 0; } diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 1329d02f873..42c9ab29ca8 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -119,8 +119,12 @@ struct gpio_desc { unsigned long flags; #define GPIOD_IS_OUT BIT(1) /* GPIO is an output */ #define GPIOD_IS_IN BIT(2) /* GPIO is an input */ -#define GPIOD_ACTIVE_LOW BIT(3) /* value has active low */ +#define GPIOD_ACTIVE_LOW BIT(3) /* GPIO is active when value is low */ #define GPIOD_IS_OUT_ACTIVE BIT(4) /* set output active */ +#define GPIOD_OPEN_DRAIN BIT(5) /* GPIO is open drain type */ +#define GPIOD_OPEN_SOURCE BIT(6) /* GPIO is open source type */ +#define GPIOD_PULL_UP BIT(7) /* GPIO has pull-up enabled */ +#define GPIOD_PULL_DOWN BIT(8) /* GPIO has pull-down enabled */ uint offset; /* GPIO offset within the device */ /* -- cgit v1.3.1 From d2c07e56ab3ef0cec99335aa8dafbed691d23739 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 13 Jan 2020 11:35:08 +0100 Subject: gpio: add ops to get dir flags Add the ops for GPIO driver get_dir_flags(), allows to get dynamically the current gpio configuration; it is used by the API function dm_gpio_get_dir_flags(). When these optional ops are absent, the gpio uclass continues to use the mandatory ops (direction_output, direction_input, get_value) and value of desc->flags to manage only the main dir flags: - GPIOD_IS_IN - GPIOD_IS_OUT - GPIOD_IS_OUT_ACTIVE - GPIOD_ACTIVE_LOW Signed-off-by: Patrick Delaunay Reviewed-by: Simon Glass --- drivers/gpio/gpio-uclass.c | 31 +++++++++++++++++++++++++------ include/asm-generic/gpio.h | 15 +++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) (limited to 'include/asm-generic') diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 25263994d24..84e5013cceb 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -614,19 +614,36 @@ int dm_gpio_set_dir(struct gpio_desc *desc) int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags) { - int ret; + struct udevice *dev = desc->dev; + int ret, value; + struct dm_gpio_ops *ops = gpio_get_ops(dev); ulong dir_flags; ret = check_reserved(desc, "get_dir_flags"); if (ret) return ret; - dir_flags = desc->flags; - /* only GPIOD_IS_OUT_ACTIVE is provided by uclass */ - dir_flags &= ~GPIOD_IS_OUT_ACTIVE; - if ((desc->flags & GPIOD_IS_OUT) && _gpio_get_value(desc)) - dir_flags |= GPIOD_IS_OUT_ACTIVE; + /* GPIOD_ are directly provided by driver except GPIOD_ACTIVE_LOW */ + if (ops->get_dir_flags) { + ret = ops->get_dir_flags(dev, desc->offset, &dir_flags); + if (ret) + return ret; + /* GPIOD_ACTIVE_LOW is saved in desc->flags */ + value = dir_flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0; + if (desc->flags & GPIOD_ACTIVE_LOW) + value = !value; + dir_flags &= ~(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE); + dir_flags |= (desc->flags & GPIOD_ACTIVE_LOW); + if (value) + dir_flags |= GPIOD_IS_OUT_ACTIVE; + } else { + dir_flags = desc->flags; + /* only GPIOD_IS_OUT_ACTIVE is provided by uclass */ + dir_flags &= ~GPIOD_IS_OUT_ACTIVE; + if ((desc->flags & GPIOD_IS_OUT) && _gpio_get_value(desc)) + dir_flags |= GPIOD_IS_OUT_ACTIVE; + } *flags = dir_flags; return 0; @@ -1129,6 +1146,8 @@ static int gpio_post_bind(struct udevice *dev) ops->get_function += gd->reloc_off; if (ops->xlate) ops->xlate += gd->reloc_off; + if (ops->get_dir_flags) + ops->get_dir_flags += gd->reloc_off; reloc_done++; } diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 42c9ab29ca8..7c1f71b1acc 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -297,6 +297,21 @@ struct dm_gpio_ops { */ int (*xlate)(struct udevice *dev, struct gpio_desc *desc, struct ofnode_phandle_args *args); + + /** + * get_dir_flags() - Get GPIO dir flags + * + * This function return the GPIO direction flags used. + * + * This method is optional. + * + * @dev: GPIO device + * @offset: GPIO offset within that device + * @flags: place to put the used direction flags by GPIO + * @return 0 if OK, -ve on error + */ + int (*get_dir_flags)(struct udevice *dev, unsigned int offset, + ulong *flags); }; /** -- cgit v1.3.1 From 8fd9daf0363e6d0bda8cc9a6330eb08a0c98543f Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 13 Jan 2020 11:35:09 +0100 Subject: gpio: add ops to set dir flags Add the ops for GPIO driver set_dir_flags() to set the dir flags. The user can update the direction and configuration of each GPIO with a only call to dm_gpio_set_dir_flags() or dm_gpio_set_dir() and respecting the configuration provided by device tree (saved in desc->flags). When these optional ops are absent, the gpio uclass use the mandatory ops (direction_output, direction_input, get_value) and desc->flags to manage only the main dir flags: - GPIOD_IS_IN - GPIOD_IS_OUT - GPIOD_IS_OUT_ACTIVE - GPIOD_ACTIVE_LOW Signed-off-by: Patrick Delaunay Reviewed-by: Simon Glass --- drivers/gpio/gpio-uclass.c | 17 ++++++++++++----- include/asm-generic/gpio.h | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) (limited to 'include/asm-generic') diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 84e5013cceb..757ab7106ee 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -572,11 +572,16 @@ static int _dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) return ret; } - if (flags & GPIOD_IS_OUT) { - ret = ops->direction_output(dev, desc->offset, - GPIOD_FLAGS_OUTPUT(flags)); - } else if (flags & GPIOD_IS_IN) { - ret = ops->direction_input(dev, desc->offset); + /* GPIOD_ are directly managed by driver in set_dir_flags*/ + if (ops->set_dir_flags) { + ret = ops->set_dir_flags(dev, desc->offset, flags); + } else { + if (flags & GPIOD_IS_OUT) { + ret = ops->direction_output(dev, desc->offset, + GPIOD_FLAGS_OUTPUT(flags)); + } else if (flags & GPIOD_IS_IN) { + ret = ops->direction_input(dev, desc->offset); + } } return ret; @@ -1146,6 +1151,8 @@ static int gpio_post_bind(struct udevice *dev) ops->get_function += gd->reloc_off; if (ops->xlate) ops->xlate += gd->reloc_off; + if (ops->set_dir_flags) + ops->set_dir_flags += gd->reloc_off; if (ops->get_dir_flags) ops->get_dir_flags += gd->reloc_off; diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 7c1f71b1acc..859f41a0d41 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -298,6 +298,22 @@ struct dm_gpio_ops { int (*xlate)(struct udevice *dev, struct gpio_desc *desc, struct ofnode_phandle_args *args); + /** + * set_dir_flags() - Set GPIO dir flags + * + * This function should set up the GPIO configuration according to the + * information provide by the direction flags bitfield. + * + * This method is optional. + * + * @dev: GPIO device + * @offset: GPIO offset within that device + * @flags: GPIO configuration to use + * @return 0 if OK, -ve on error + */ + int (*set_dir_flags)(struct udevice *dev, unsigned int offset, + ulong flags); + /** * get_dir_flags() - Get GPIO dir flags * -- cgit v1.3.1