From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Ahmad Fatoum <a.fatoum@pengutronix.de>
Subject: [PATCH 07/11] gpiolib: add support for OF GPIO configuration binding
Date: Fri, 9 Aug 2024 16:24:01 +0200 [thread overview]
Message-ID: <20240809142405.315244-8-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20240809142405.315244-1-a.fatoum@pengutronix.de>
Previous commits laid the groundwork:
- Flags in the DT are saved into GPIO descriptors
- GPIO drivers can implement a set_config operation
Let's wire them together, so we call the set_config operation when
requesting a GPIO as necessary.
For this to be usable:
- The GPIO consumer must request the GPIO with gpiod_get
- The GPIO provider must implement set_config
This is not yet the case for the overwhelming majority of barebox GPIO
consumers and providers, so we allow disabling this functionality via a
Kconfig option.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/gpio/gpiolib.c | 94 +++++++++++++++++++++++++++++++++++++++++-
drivers/of/Kconfig | 15 +++++++
include/of_gpio.h | 5 +++
3 files changed, 112 insertions(+), 2 deletions(-)
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 539fd3c7c25f..4a1792a8df1f 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -8,6 +8,7 @@
#include <gpio.h>
#include <of_gpio.h>
#include <linux/gpio/consumer.h>
+#include <linux/pinctrl/pinconf-generic.h>
#include <linux/overflow.h>
#include <errno.h>
#include <malloc.h>
@@ -437,6 +438,61 @@ int gpio_direction_output(unsigned gpio, int value)
}
EXPORT_SYMBOL(gpio_direction_output);
+static int gpio_set_config_with_argument(struct gpio_desc *desc,
+ enum pin_config_param mode,
+ u32 argument)
+{
+ unsigned long config;
+
+ config = pinconf_to_config_packed(mode, argument);
+ return gpio_do_set_config(desc->chip, gpiodesc_chip_offset(desc), config);
+}
+
+static int gpio_set_config_with_argument_optional(struct gpio_desc *desc,
+ enum pin_config_param mode,
+ u32 argument)
+{
+ int ret;
+
+ ret = gpio_set_config_with_argument(desc, mode, argument);
+ if (ret != -ENOTSUPP)
+ return ret;
+ return 0;
+}
+
+static int gpio_set_config(struct gpio_desc *desc, enum pin_config_param mode)
+{
+ return gpio_set_config_with_argument(desc, mode, 0);
+}
+
+static int gpio_set_bias(struct gpio_desc *desc)
+{
+ enum pin_config_param bias;
+ unsigned int arg;
+
+ if (desc->flags & OF_GPIO_PULL_DISABLE)
+ bias = PIN_CONFIG_BIAS_DISABLE;
+ else if (desc->flags & OF_GPIO_PULL_UP)
+ bias = PIN_CONFIG_BIAS_PULL_UP;
+ else if (desc->flags & OF_GPIO_PULL_DOWN)
+ bias = PIN_CONFIG_BIAS_PULL_DOWN;
+ else
+ return 0;
+
+ switch (bias) {
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_BIAS_PULL_UP:
+ arg = 1;
+ break;
+
+ default:
+ arg = 0;
+ break;
+ }
+
+ return gpio_set_config_with_argument_optional(desc, bias, arg);
+}
+
/**
* gpiod_direction_output - set the GPIO direction to output
* @desc: GPIO to set to output
@@ -451,8 +507,36 @@ EXPORT_SYMBOL(gpio_direction_output);
*/
int gpiod_direction_output(struct gpio_desc *desc, int value)
{
+ int ret;
+
VALIDATE_DESC(desc);
+ if (IS_ENABLED(CONFIG_GPIO_PINCONF)) {
+ if (desc->flags & (OF_GPIO_OPEN_DRAIN | OF_GPIO_SINGLE_ENDED)) {
+ /* First see if we can enable open drain in hardware */
+ ret = gpio_set_config(desc, PIN_CONFIG_DRIVE_OPEN_DRAIN);
+ if (!ret)
+ goto set_output_value;
+ /* Emulate open drain by not actively driving the line high */
+ if (value)
+ return gpiod_direction_input(desc);
+ } else if (desc->flags & OF_GPIO_SINGLE_ENDED) {
+ ret = gpio_set_config(desc, PIN_CONFIG_DRIVE_OPEN_SOURCE);
+ if (!ret)
+ goto set_output_value;
+ /* Emulate open source by not actively driving the line low */
+ if (!value)
+ return gpiod_direction_input(desc);
+ } else {
+ gpio_set_config(desc, PIN_CONFIG_DRIVE_PUSH_PULL);
+ }
+
+set_output_value:
+ ret = gpio_set_bias(desc);
+ if (ret)
+ return ret;
+ }
+
return gpiod_direction_output_raw(desc, gpio_adjust_value(desc, value));
}
@@ -478,13 +562,19 @@ EXPORT_SYMBOL(gpio_direction_active);
*/
int gpiod_direction_input(struct gpio_desc *desc)
{
+ int ret;
+
VALIDATE_DESC(desc);
if (!desc->chip->ops->direction_input)
return -ENOSYS;
- return desc->chip->ops->direction_input(desc->chip,
- gpiodesc_chip_offset(desc));
+ ret = desc->chip->ops->direction_input(desc->chip,
+ gpiodesc_chip_offset(desc));
+ if (ret == 0 && IS_ENABLED(CONFIG_GPIO_PINCONF))
+ ret = gpio_set_bias(desc);
+
+ return ret;
}
EXPORT_SYMBOL(gpiod_direction_input);
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 2791100a2d9c..6c9aedf355b4 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -40,6 +40,21 @@ config OF_GPIO
depends on OFDEVICE
def_bool y
+config OF_GPIO_PINCONF
+ depends on OF_GPIO && HAVE_GPIO_PINCONF
+ select GPIO_PINCONF
+ bool "Enable support for extra GPIO pin configuration binding"
+ default y
+ help
+ In addition to the normal pinctrl-names/pinctrl-X binding, there's
+ also a binding to add flags like GPIO_OPEN_DRAIN or GPIO_PULL_UP
+ OR-ed into the cell of the gpios property used for
+ GPIO_ACTIVE_HIGH/LOW. This latter binding is optional and many
+ drivers don't support it.
+
+ If unsure and not size conscious, say y here to enable the
+ extra binding.
+
config OF_PCI
bool
depends on PCI
diff --git a/include/of_gpio.h b/include/of_gpio.h
index a7a3493473c8..4ab5de6ed580 100644
--- a/include/of_gpio.h
+++ b/include/of_gpio.h
@@ -17,6 +17,11 @@
*/
enum of_gpio_flags {
OF_GPIO_ACTIVE_LOW = 0x1,
+ OF_GPIO_SINGLE_ENDED = 0x2,
+ OF_GPIO_OPEN_DRAIN = 0x4,
+ OF_GPIO_PULL_UP = 0x10,
+ OF_GPIO_PULL_DOWN = 0x20,
+ OF_GPIO_PULL_DISABLE = 0x40,
OF_GPIO_REQUESTED = 0x80000000, /* internal use */
};
--
2.39.2
next prev parent reply other threads:[~2024-08-09 14:24 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-09 14:23 [PATCH 00/11] " Ahmad Fatoum
2024-08-09 14:23 ` [PATCH 01/11] gpio: make gpio.h header self-contained Ahmad Fatoum
2024-08-09 14:23 ` [PATCH 02/11] gpiolib: permit GPIO drivers to implement struct gpio_ops::set_config Ahmad Fatoum
2024-08-09 14:23 ` [PATCH 03/11] pinctrl: stm32: implement generic " Ahmad Fatoum
2024-08-09 14:23 ` [PATCH 04/11] gpiolib: turn request/active_low into bit flags Ahmad Fatoum
2024-08-09 14:23 ` [PATCH 05/11] gpiolib: don't use GPIO number API in of_hog_gpio Ahmad Fatoum
2024-08-09 14:24 ` [PATCH 06/11] gpiolib: store all OF flags into GPIO descriptor Ahmad Fatoum
2024-08-09 14:24 ` Ahmad Fatoum [this message]
2024-08-09 14:24 ` [PATCH 08/11] gpiolib: use dev_gpiod_get_index device node argument throughout Ahmad Fatoum
2024-08-09 14:24 ` [PATCH 09/11] gpiolib: export function to get struct gpio_desc from index Ahmad Fatoum
2024-08-09 14:24 ` [PATCH 10/11] input: gpio_keys: switch to GPIO descriptor API Ahmad Fatoum
2024-08-09 14:24 ` [PATCH 11/11] input: gpio-keys: request with label in DT if available Ahmad Fatoum
2024-08-14 11:00 ` [PATCH 00/11] gpiolib: add support for OF GPIO configuration binding Sascha Hauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240809142405.315244-8-a.fatoum@pengutronix.de \
--to=a.fatoum@pengutronix.de \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox