mail archive of the barebox mailing list
 help / color / mirror / Atom feed
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




  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