[PATCH 02/11] gpiolib: permit GPIO drivers to implement struct gpio_ops::set_config

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



So far, GPIO bias configuration was done exclusively by pinctrl drivers.
All barebox pinctrl drivers work by consuming a device tree node with
a binding that differs from driver to driver and then applying the
configuration described within.

Neither GPIO or pinctrl node have any insight on what in particular is
being configured.

This is problematic when wanting to support following device tree
binding, which is so far being ignored:

  gpios = <&gpioe 7 (GPIO_ACTIVE_LOW | GPIO_PULL_DOWN)>;

In preparation for enabling support, let's give GPIO drivers a way to
set configuration. This will be implemented by the STM32 pinctrl/gpio
driver in a follow-up commit.

The new functionality will be selected by a new OF_GPIO_PINCONF option
that is going to be introduced later.

Signed-off-by: Ahmad Fatoum <a.fatoum@xxxxxxxxxxxxxx>
---
 drivers/gpio/Kconfig          | 14 ++++++++++++++
 drivers/gpio/gpiolib.c        | 28 ++++++++++++++++++++++++++++
 include/gpio.h                |  1 +
 include/linux/gpio/consumer.h |  9 +++++++++
 4 files changed, 52 insertions(+)

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index d9bb68e06b25..76b11d93aa64 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -10,6 +10,20 @@ menu "GPIO"
 config GPIO_GENERIC
 	bool
 
+config HAVE_GPIO_PINCONF
+	bool
+	help
+	  This is selected by drivers who implement struct gpio_ops::set_config
+
+config GPIO_PINCONF
+	bool "support for configuring GPIO lines directly" if COMPILE_TEST
+	help
+	  This option enables compilation and use of the optional
+	  struct gpio_ops::set_config callback. Drivers that export
+	  it allow configuring bias and other configuration directly
+	  on the GPIO line without having to interact directly with
+	  the pinctrl subsystem.
+
 config GPIO_DIGIC
 	bool "GPIO support for Canon DIGIC"
 	depends on ARCH_DIGIC || COMPILE_TEST
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index f34dce0e98c6..e8d788d4d791 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -238,6 +238,34 @@ void gpiod_put_array(struct gpio_descs *descs)
 }
 EXPORT_SYMBOL_GPL(gpiod_put_array);
 
+static int gpio_do_set_config(struct gpio_chip *gc, unsigned int offset,
+			      unsigned long config)
+{
+	if (!IS_ENABLED(CONFIG_GPIO_PINCONF))
+		return -ENOSYS;
+	if (!gc->ops->set_config)
+		return -ENOTSUPP;
+
+	return gc->ops->set_config(gc, offset, config);
+}
+
+/**
+ * gpiod_set_config - sets @config for a GPIO
+ * @desc: descriptor of the GPIO for which to set the configuration
+ * @config: Same packed config format as generic pinconf
+ *
+ * Returns:
+ * 0 on success, %-ENOTSUPP if the controller doesn't support setting the
+ * configuration.
+ */
+int gpiod_set_config(struct gpio_desc *desc, unsigned long config)
+{
+	VALIDATE_DESC(desc);
+
+	return gpio_do_set_config(desc->chip, gpiodesc_chip_offset(desc), config);
+}
+EXPORT_SYMBOL_GPL(gpiod_set_config);
+
 /**
  * gpiod_set_raw_value() - assign a gpio's raw value
  * @desc: gpio whose value will be assigned
diff --git a/include/gpio.h b/include/gpio.h
index cc56c91c3ee2..beda10efde08 100644
--- a/include/gpio.h
+++ b/include/gpio.h
@@ -195,6 +195,7 @@ struct gpio_ops {
 	int (*get_direction)(struct gpio_chip *chip, unsigned offset);
 	int (*get)(struct gpio_chip *chip, unsigned offset);
 	void (*set)(struct gpio_chip *chip, unsigned offset, int value);
+	int (*set_config)(struct gpio_chip *chip, unsigned offset, unsigned long config);
 
 #if defined(CONFIG_OF_GPIO)
 	/*
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index e04f516b3155..64366a6f3302 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -69,6 +69,8 @@ static inline struct gpio_desc *dev_gpiod_get_index(struct device *dev,
 
 #ifdef CONFIG_GPIOLIB
 
+int gpiod_set_config(struct gpio_desc *desc, unsigned long config);
+
 int gpiod_direction_input(struct gpio_desc *desc);
 
 int gpiod_direction_output_raw(struct gpio_desc *desc, int value);
@@ -97,6 +99,13 @@ int gpiod_set_array_value(unsigned int array_size,
 
 #else
 
+static inline int gpiod_set_config(struct gpio_desc *desc, unsigned long config)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(desc);
+	return 0;
+}
+
 static inline int gpiod_direction_input(struct gpio_desc *desc)
 {
 	/* GPIO can never have been requested */
-- 
2.39.2





[Index of Archives]     [Linux Embedded]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux