Skip to contentSkip to conversation

gpio: add pinctrl based generic gpio driver

PATCH Superseded Dan Carpenter 4 participants 14 messages Mar 17 – Mar 18

Subsystems (4)

v4 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

v4 cover gpio: add pinctrl based generic gpio driver

This basically abandons my earlier attempts and goes back to Takahiro Akashi's driver. Here is the link to Takahiro's patchset:

https://lore.kernel.org/all/[email protected]/

v4: Addressed Andy's comments about kernel-doc
Addressed Rob's comments on the spec file
v3: Forward ported Takahiro's patches and added some fixes ups to make
it work on current kernels.

AKASHI Takahiro (3):
pinctrl: introduce pinctrl_gpio_get_config()
dt-bindings: gpio: Add bindings for pinctrl based generic gpio driver
gpio: add pinctrl based generic gpio driver

Dan Carpenter (4):
pinctrl: scmi: Add SCMI_PIN_INPUT_VALUE
pinctrl: Delete PIN_CONFIG_OUTPUT_IMPEDANCE_OHMS support
pinctrl-scmi: ignore PIN_CONFIG_PERSIST_STATE
arm_scmi: pinctrl: allow PINCTRL_REQUEST to return EOPNOTSUPP

 .../bindings/gpio/pin-control-gpio.yaml       |  59 +++++++++
 drivers/firmware/arm_scmi/pinctrl.c           |   2 +
 drivers/gpio/Kconfig                          |   7 +
 drivers/gpio/Makefile                         |   1 +
 drivers/gpio/gpio-by-pinctrl.c                | 124 ++++++++++++++++++
 drivers/pinctrl/core.c                        |  31 +++++
 drivers/pinctrl/pinctrl-scmi.c                |  46 +++++--
 include/linux/pinctrl/consumer.h              |   9 ++
 8 files changed, 266 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/gpio/pin-control-gpio.yaml
 create mode 100644 drivers/gpio/gpio-by-pinctrl.c
Signature · 1 line
2.51.0
#1 lore raw

PATCH v4 1/7 pinctrl: introduce pinctrl_gpio_get_config()

From: AKASHI Takahiro <[email protected]>

This is a counterpart of pinctrl_gpio_set_config(), which will be used to implement the ->get() interface in a GPIO driver for SCMI.

---
v4: Fix kernel-doc (Andy)

 drivers/pinctrl/core.c           | 31 +++++++++++++++++++++++++++++++
 include/linux/pinctrl/consumer.h |  9 +++++++++
 2 files changed, 40 insertions(+)
drivers/pinctrl/core.c +31 -0
index 2edc9bdad183..c471f3fbd035 100644
@@ -30,6 +30,7 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/pinctrl/devinfo.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
 #include <linux/pinctrl/pinctrl.h>
 
 #include "core.h"
@@ -938,6 +939,36 @@ int pinctrl_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
 }
 EXPORT_SYMBOL_GPL(pinctrl_gpio_set_config);
 
+/**
+ * pinctrl_gpio_get_config() - Get the config for a given GPIO pin
+ * @gc: GPIO chip structure from the GPIO subsystem
+ * @offset: hardware offset of the GPIO relative to the controller
+ * @config: the configuration to query.  On success it holds the result
+ * Return: 0 on success, negative errno otherwise
+ */
+int pinctrl_gpio_get_config(struct gpio_chip *gc, unsigned int offset, unsigned long *config)
+{
+	struct pinctrl_gpio_range *range;
+	struct pinctrl_dev *pctldev;
+	int ret, pin;
+
+	ret = pinctrl_get_device_gpio_range(gc, offset, &pctldev, &range);
+	if (ret)
+		return ret;
+
+	mutex_lock(&pctldev->mutex);
+	pin = gpio_to_pin(range, gc, offset);
+	ret = pin_config_get_for_pin(pctldev, pin, config);
+	mutex_unlock(&pctldev->mutex);
+
+	if (ret)
+		return ret;
+
+	*config = pinconf_to_config_argument(*config);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pinctrl_gpio_get_config);
+
 static struct pinctrl_state *find_state(struct pinctrl *p,
 					const char *name)
 {
include/linux/pinctrl/consumer.h +9 -0
index 63ce16191eb9..11b8f0b8da0c 100644
@@ -35,6 +35,8 @@ int pinctrl_gpio_direction_output(struct gpio_chip *gc,
 				  unsigned int offset);
 int pinctrl_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
 				unsigned long config);
+int pinctrl_gpio_get_config(struct gpio_chip *gc, unsigned int offset,
+			    unsigned long *config);
 
 struct pinctrl * __must_check pinctrl_get(struct device *dev);
 void pinctrl_put(struct pinctrl *p);
@@ -101,6 +103,13 @@ pinctrl_gpio_direction_output(struct gpio_chip *gc, unsigned int offset)
 	return 0;
 }
 
+static inline int
+pinctrl_gpio_get_config(struct gpio_chip *gc, unsigned int offset,
+			unsigned long *config)
+{
+	return 0;
+}
+
 static inline int
 pinctrl_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
 			    unsigned long config)
Signature · 1 line
2.51.0
Reviewed-by on v4 1/7
#2 lore raw

Re: [PATCH v4 1/7] pinctrl: introduce pinctrl_gpio_get_config()

Quoted 2 lines · Dan Carpenter

This is a counterpart of pinctrl_gpio_set_config(), which will be used to implement the ->get() interface in a GPIO driver for SCMI.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#3 lore raw

PATCH v4 2/7 pinctrl: scmi: Add SCMI_PIN_INPUT_VALUE

In reply to Dan Carpenter

The PIN_CONFIG_LEVEL parameter represents the value of the pin, whether reading or writing to the pin. In SCMI, the parameter is represented by two different values SCMI_PIN_OUTPUT_VALUE for writing to a pin and SCMI_PIN_INPUT_VALUE for reading. The current code translates PIN_CONFIG_LEVEL as SCMI_PIN_OUTPUT_VALUE (writing).

Add a function to translate it to either INPUT or OUTPUT depending on whether it is called from a _get or _set() operation.

---
 drivers/pinctrl/pinctrl-scmi.c | 33 ++++++++++++++++++++++++++-------
 1 file changed, 26 insertions(+), 7 deletions(-)
drivers/pinctrl/pinctrl-scmi.c +26 -7
index f4f296e07be5..5d347e6b2e4c 100644
@@ -251,9 +251,6 @@ static int pinctrl_scmi_map_pinconf_type(enum pin_config_param param,
 	case PIN_CONFIG_MODE_LOW_POWER:
 		*type = SCMI_PIN_LOW_POWER_MODE;
 		break;
-	case PIN_CONFIG_LEVEL:
-		*type = SCMI_PIN_OUTPUT_VALUE;
-		break;
 	case PIN_CONFIG_OUTPUT_ENABLE:
 		*type = SCMI_PIN_OUTPUT_MODE;
 		break;
@@ -276,6 +273,28 @@ static int pinctrl_scmi_map_pinconf_type(enum pin_config_param param,
 	return 0;
 }
 
+static int pinctrl_scmi_map_pinconf_type_get(enum pin_config_param param,
+					     enum scmi_pinctrl_conf_type *type)
+{
+	if (param == PIN_CONFIG_LEVEL) {
+		*type = SCMI_PIN_INPUT_VALUE;
+		return 0;
+	}
+
+	return pinctrl_scmi_map_pinconf_type(param, type);
+}
+
+static int pinctrl_scmi_map_pinconf_type_set(enum pin_config_param param,
+					     enum scmi_pinctrl_conf_type *type)
+{
+	if (param == PIN_CONFIG_LEVEL) {
+		*type = SCMI_PIN_OUTPUT_VALUE;
+		return 0;
+	}
+
+	return pinctrl_scmi_map_pinconf_type(param, type);
+}
+
 static int pinctrl_scmi_pinconf_get(struct pinctrl_dev *pctldev,
 				    unsigned int pin, unsigned long *config)
 {
@@ -290,7 +309,7 @@ static int pinctrl_scmi_pinconf_get(struct pinctrl_dev *pctldev,
 
 	config_type = pinconf_to_config_param(*config);
 
-	ret = pinctrl_scmi_map_pinconf_type(config_type, &type);
+	ret = pinctrl_scmi_map_pinconf_type_get(config_type, &type);
 	if (ret)
 		return ret;
 
@@ -363,7 +382,7 @@ static int pinctrl_scmi_pinconf_set(struct pinctrl_dev *pctldev,
 
 	for (i = 0; i < num_configs; i++) {
 		param = pinconf_to_config_param(configs[i]);
-		ret = pinctrl_scmi_map_pinconf_type(param, &p_config_type[i]);
+		ret = pinctrl_scmi_map_pinconf_type_set(param, &p_config_type[i]);
 		if (ret) {
 			dev_err(pmx->dev, "Error map pinconf_type %d\n", ret);
 			goto free_config;
@@ -405,7 +424,7 @@ static int pinctrl_scmi_pinconf_group_set(struct pinctrl_dev *pctldev,
 
 	for (i = 0; i < num_configs; i++) {
 		param = pinconf_to_config_param(configs[i]);
-		ret = pinctrl_scmi_map_pinconf_type(param, &p_config_type[i]);
+		ret = pinctrl_scmi_map_pinconf_type_set(param, &p_config_type[i]);
 		if (ret) {
 			dev_err(pmx->dev, "Error map pinconf_type %d\n", ret);
 			goto free_config;
@@ -440,7 +459,7 @@ static int pinctrl_scmi_pinconf_group_get(struct pinctrl_dev *pctldev,
 		return -EINVAL;
 
 	config_type = pinconf_to_config_param(*config);
-	ret = pinctrl_scmi_map_pinconf_type(config_type, &type);
+	ret = pinctrl_scmi_map_pinconf_type_get(config_type, &type);
 	if (ret) {
 		dev_err(pmx->dev, "Error map pinconf_type %d\n", ret);
 		return ret;
Signature · 1 line
2.51.0
#4 lore raw

Re: [PATCH v4 2/7] pinctrl: scmi: Add SCMI_PIN_INPUT_VALUE

Quoted 8 lines · Dan Carpenter

The PIN_CONFIG_LEVEL parameter represents the value of the pin, whether reading or writing to the pin. In SCMI, the parameter is represented by two different values SCMI_PIN_OUTPUT_VALUE for writing to a pin and SCMI_PIN_INPUT_VALUE for reading. The current code translates PIN_CONFIG_LEVEL as SCMI_PIN_OUTPUT_VALUE (writing).

Add a function to translate it to either INPUT or OUTPUT depending on whether it is called from a _get or _set() operation.

In three consecutive patches against the same file you have three (!) different prefixes. Please, align with what is being used most in the driver and/or subsystem (the driver seems has no consensus with itself, so subsystem then, something like
"pinctrl: scmi: ").

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#5 lore raw

Re: [PATCH v4 2/7] pinctrl: scmi: Add SCMI_PIN_INPUT_VALUE

Quoted 7 lines · Andy Shevchenko
Quoted 6 lines · Dan Carpenter

The PIN_CONFIG_LEVEL parameter represents the value of the pin, whether reading or writing to the pin. In SCMI, the parameter is represented by two different values SCMI_PIN_OUTPUT_VALUE for writing to a pin and SCMI_PIN_INPUT_VALUE for reading. The current code translates PIN_CONFIG_LEVEL as SCMI_PIN_OUTPUT_VALUE (writing).

Quoted 7 lines
Quoted 2 lines

Add a function to translate it to either INPUT or OUTPUT depending on whether it is called from a _get or _set() operation.

In three consecutive patches against the same file you have three (!) different prefixes. Please, align with what is being used most in the driver and/or subsystem (the driver seems has no consensus with itself, so subsystem then, something like
"pinctrl: scmi: ").

Oops. Crud. You're right.

regards,
dan carpenter

#6 lore raw

PATCH v4 3/7 pinctrl: Delete PIN_CONFIG_OUTPUT_IMPEDANCE_OHMS support

In reply to Dan Carpenter

The argument for PIN_CONFIG_OUTPUT_IMPEDANCE_OHMS is supposed to be expressed in terms of ohms. But the pinctrl-scmi driver was implementing it the same as PIN_CONFIG_OUTPUT and writing either a zero or one to the pin.

The SCMI protocol doesn't have an support configuration type so just delete this code instead of replacing it.

---
 drivers/pinctrl/pinctrl-scmi.c | 3 ---
 1 file changed, 3 deletions(-)
drivers/pinctrl/pinctrl-scmi.c +0 -3
index 5d347e6b2e4c..de8c113bc61d 100644
@@ -254,9 +254,6 @@ static int pinctrl_scmi_map_pinconf_type(enum pin_config_param param,
 	case PIN_CONFIG_OUTPUT_ENABLE:
 		*type = SCMI_PIN_OUTPUT_MODE;
 		break;
-	case PIN_CONFIG_OUTPUT_IMPEDANCE_OHMS:
-		*type = SCMI_PIN_OUTPUT_VALUE;
-		break;
 	case PIN_CONFIG_POWER_SOURCE:
 		*type = SCMI_PIN_POWER_SOURCE;
 		break;
Signature · 1 line
2.51.0
#7 lore raw

PATCH v4 4/7 pinctrl-scmi: ignore PIN_CONFIG_PERSIST_STATE

In reply to Dan Carpenter

The PIN_CONFIG_PERSIST_STATE setting ensures that the pin state persists across a sleep or controller reset. The SCMI spec does not have an equivalent command to this so just ignore it.

---
 drivers/pinctrl/pinctrl-scmi.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/pinctrl/pinctrl-scmi.c +8 -4
index de8c113bc61d..f22be6b7b82a 100644
@@ -361,7 +361,7 @@ static int pinctrl_scmi_pinconf_set(struct pinctrl_dev *pctldev,
 				    unsigned long *configs,
 				    unsigned int num_configs)
 {
-	int i, ret;
+	int i, cnt, ret;
 	struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
 	enum scmi_pinctrl_conf_type config_type[SCMI_NUM_CONFIGS];
 	u32 config_value[SCMI_NUM_CONFIGS];
@@ -377,17 +377,21 @@ static int pinctrl_scmi_pinconf_set(struct pinctrl_dev *pctldev,
 	if (ret)
 		return ret;
 
+	cnt = 0;
 	for (i = 0; i < num_configs; i++) {
 		param = pinconf_to_config_param(configs[i]);
-		ret = pinctrl_scmi_map_pinconf_type_set(param, &p_config_type[i]);
+		if (param == PIN_CONFIG_PERSIST_STATE)
+			continue;
+		ret = pinctrl_scmi_map_pinconf_type_set(param, &p_config_type[cnt]);
 		if (ret) {
 			dev_err(pmx->dev, "Error map pinconf_type %d\n", ret);
 			goto free_config;
 		}
-		p_config_value[i] = pinconf_to_config_argument(configs[i]);
+		p_config_value[cnt] = pinconf_to_config_argument(configs[i]);
+		cnt++;
 	}
 
-	ret = pinctrl_ops->settings_conf(pmx->ph, pin, PIN_TYPE, num_configs,
+	ret = pinctrl_ops->settings_conf(pmx->ph, pin, PIN_TYPE, cnt,
 					 p_config_type,  p_config_value);
 	if (ret)
 		dev_err(pmx->dev, "Error parsing config %d\n", ret);
Signature · 1 line
2.51.0
#8 lore raw

PATCH v4 5/7 arm_scmi: pinctrl: allow PINCTRL_REQUEST to return EOPNOTSUPP

In reply to Dan Carpenter

The SCMI protocol specification says that the PINCTRL_REQUEST and PINCTRL_RELEASE commands are optional. So if the SCMI server returns -EOPNOTSUPP, then treat that as success and continue.

---
 drivers/firmware/arm_scmi/pinctrl.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/firmware/arm_scmi/pinctrl.c +2 -0
index a020e23d7c49..42cb1aef1fe1 100644
@@ -578,6 +578,8 @@ static int scmi_pinctrl_request_free(const struct scmi_protocol_handle *ph,
 	tx->flags = cpu_to_le32(type);
 
 	ret = ph->xops->do_xfer(ph, t);
+	if (ret == -EOPNOTSUPP)
+		ret = 0;
 	ph->xops->xfer_put(ph, t);
 
 	return ret;
Signature · 1 line
2.51.0
#9 lore raw

Re: [PATCH v4 5/7] arm_scmi: pinctrl: allow PINCTRL_REQUEST to return EOPNOTSUPP

Quoted 3 lines · Dan Carpenter

The SCMI protocol specification says that the PINCTRL_REQUEST and PINCTRL_RELEASE commands are optional. So if the SCMI server returns -EOPNOTSUPP, then treat that as success and continue.

Hi

a nitpick, this should be

firmware: arm_scmi: Allow PINCTRL_REQUEST to return EOPNOTSUPP

Thanks,
Cristian

Quoted 24 lines
---
 drivers/firmware/arm_scmi/pinctrl.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/firmware/arm_scmi/pinctrl.c +2 -0
index a020e23d7c49..42cb1aef1fe1 100644
@@ -578,6 +578,8 @@ static int scmi_pinctrl_request_free(const struct scmi_protocol_handle *ph,
 	tx->flags = cpu_to_le32(type);
 
 	ret = ph->xops->do_xfer(ph, t);
+	if (ret == -EOPNOTSUPP)
+		ret = 0;
 	ph->xops->xfer_put(ph, t);
 
 	return ret;
Signature · 1 line
2.51.0
#10 lore raw

PATCH v4 6/7 dt-bindings: gpio: Add bindings for pinctrl based generic gpio driver

In reply to Dan Carpenter

From: AKASHI Takahiro <[email protected]>

Add a dt binding for the gpio-by-pinctrl driver. The driver is used for doing GPIO over the SCMI pinctrl protocol. There are a few mandatory properties such as gpio-ranges and ngpios, but it's not mandatory to specify the pin-mux.

---
v4: Changed additionalProperties: true to false.

My concern here was that there might be a lot of gpio properties which I wasn't familiar with. To check I did:
grep :$ Documentation/devicetree/bindings/gpio/* | \
cut -d : -f 2- | perl -ne 's/[\ ]*//g; print "$_\n"' | \
sort | uniq -c
The only property that I decided to add was gpio-line-names.

Deleted the extra bonus example.

 .../bindings/gpio/pin-control-gpio.yaml       | 59 +++++++++++++++++++
 1 file changed, 59 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/pin-control-gpio.yaml
Documentation/devicetree/bindings/gpio/pin-control-gpio.yaml new file +59 -0
new file mode 100644
index 000000000000..ebc3fdd039fd
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpio/pin-control-gpio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Pin control based generic GPIO controller
+
+description:
+  The pin control-based GPIO will facilitate a pin controller's ability
+  to drive electric lines high/low and other generic properties of a
+  pin controller to perform general-purpose one-bit binary I/O.
+
+maintainers:
+  - Dan Carpenter <[email protected]>
+
+properties:
+  compatible:
+    const: scmi-pinctrl-gpio
+
+  gpio-controller: true
+
+  "#gpio-cells":
+    const: 2
+
+  gpio-line-names: true
+
+  gpio-ranges: true
+
+  ngpios: true
+
+patternProperties:
+  "^.+-hog(-[0-9]+)?$":
+    type: object
+
+    required:
+      - gpio-hog
+
+required:
+  - compatible
+  - gpio-controller
+  - "#gpio-cells"
+  - gpio-ranges
+  - ngpios
+
+additionalProperties: false
+
+examples:
+  - |
+    gpio {
+        compatible = "scmi-pinctrl-gpio";
+        gpio-controller;
+        #gpio-cells = <2>;
+        ngpios = <3>;
+        gpio-line-names = "gpio_5_17", "gpio_5_20", "gpio_5_22", "gpio_2_1";
+        gpio-ranges = <&scmi_pinctrl 0 30 4>;
+        pinctrl-names = "default";
+        pinctrl-0 = <&keys_pins>;
+    };
Signature · 1 line
2.51.0
#11 lore raw

Re: [PATCH v4 6/7] dt-bindings: gpio: Add bindings for pinctrl based generic gpio driver

Quoted 3 lines · Dan Carpenter

From: AKASHI Takahiro <[email protected]>

Add a dt binding for the gpio-by-pinctrl driver. The driver is used

Drop all references to the driver. Describe the device/hardware/firmware/interface, not driver. Same for subject.

Quoted 3 lines

for doing GPIO over the SCMI pinctrl protocol. There are a few mandatory properties such as gpio-ranges and ngpios, but it's not mandatory to specify the pin-mux.

There is no such thing there as pin-mux, so I don't understand above sentence.

Describe the hardware/firmware/interface, not the patch, because we easily see which properties are mandatory. Schema tells that.

Quoted 4 lines

A nit, subject: drop second/last, redundant "bindings for". The "dt-bindings" prefix is already stating that these are bindings. See also:
https://elixir.bootlin.com/linux/v6.17-rc3/source/Documentation/devicetree/bindings/submitting-patches.rst#L18

Quoted 66 lines

---
v4: Changed additionalProperties: true to false.

My concern here was that there might be a lot of gpio properties which I wasn't familiar with. To check I did:
grep :$ Documentation/devicetree/bindings/gpio/* | \
cut -d : -f 2- | perl -ne 's/[\ ]*//g; print "$_\n"' | \
sort | uniq -c
The only property that I decided to add was gpio-line-names.

Deleted the extra bonus example.

 .../bindings/gpio/pin-control-gpio.yaml       | 59 +++++++++++++++++++
 1 file changed, 59 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/pin-control-gpio.yaml
Documentation/devicetree/bindings/gpio/pin-control-gpio.yaml new file +44 -0
new file mode 100644
index 000000000000..ebc3fdd039fd
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpio/pin-control-gpio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Pin control based generic GPIO controller
+
+description:
+  The pin control-based GPIO will facilitate a pin controller's ability
+  to drive electric lines high/low and other generic properties of a
+  pin controller to perform general-purpose one-bit binary I/O.
+
+maintainers:
+  - Dan Carpenter <[email protected]>
+
+properties:
+  compatible:
+    const: scmi-pinctrl-gpio
+
+  gpio-controller: true
+
+  "#gpio-cells":
+    const: 2
+
+  gpio-line-names: true
+
+  gpio-ranges: true
+
+  ngpios: true
+
+patternProperties:
+  "^.+-hog(-[0-9]+)?$":
+    type: object
+
+    required:
+      - gpio-hog
+
+required:
+  - compatible
+  - gpio-controller
+  - "#gpio-cells"
+  - gpio-ranges
+  - ngpios

Documentation/devicetree/bindings/gpio/pin-control-gpio.yaml line 54

Quoted 10 lines
Documentation/devicetree/bindings/gpio/pin-control-gpio.yaml new file +10 -0
+
+additionalProperties: false
+
+examples:
+  - |
+    gpio {
+        compatible = "scmi-pinctrl-gpio";
+        gpio-controller;
+        #gpio-cells = <2>;
+        ngpios = <3>;

Three pins here

Documentation/devicetree/bindings/gpio/pin-control-gpio.yaml line 55

Quoted 1 line
Documentation/devicetree/bindings/gpio/pin-control-gpio.yaml new file +1 -0
+        gpio-line-names = "gpio_5_17", "gpio_5_20", "gpio_5_22", "gpio_2_1";

... four here

Documentation/devicetree/bindings/gpio/pin-control-gpio.yaml line 56

Quoted 1 line
Documentation/devicetree/bindings/gpio/pin-control-gpio.yaml new file +1 -0
+        gpio-ranges = <&scmi_pinctrl 0 30 4>;

... and four here, so it feels inconsistent. I guess ngpios = 4?

Best regards,
Krzysztof

#12 lore raw

PATCH v4 7/7 gpio: add pinctrl based generic gpio driver

In reply to Dan Carpenter

From: AKASHI Takahiro <[email protected]>

The ARM SCMI pinctrl protocol allows GPIO access. Instead of creating a new SCMI gpio driver, this driver is a generic GPIO driver that uses standard pinctrl interfaces.

---
 drivers/gpio/Kconfig           |   7 ++
 drivers/gpio/Makefile          |   1 +
 drivers/gpio/gpio-by-pinctrl.c | 124 +++++++++++++++++++++++++++++++++
 3 files changed, 132 insertions(+)
 create mode 100644 drivers/gpio/gpio-by-pinctrl.c
drivers/gpio/Kconfig +7 -0
index b45fb799e36c..4c8d2589c412 100644
@@ -246,6 +246,13 @@ config GPIO_BRCMSTB
 	help
 	  Say yes here to enable GPIO support for Broadcom STB (BCM7XXX) SoCs.
 
+config GPIO_BY_PINCTRL
+	tristate "GPIO support based on a pure pin control backend"
+	depends on GPIOLIB
+	help
+	  Select this option to support GPIO devices based solely on pin
+	  control.  This is used to do GPIO over the ARM SCMI protocol.
+
 config GPIO_CADENCE
 	tristate "Cadence GPIO support"
 	depends on OF_GPIO
drivers/gpio/Makefile +1 -0
index c05f7d795c43..20d4a57afdaa 100644
@@ -51,6 +51,7 @@ obj-$(CONFIG_GPIO_BD9571MWV)		+= gpio-bd9571mwv.o
 obj-$(CONFIG_GPIO_BLZP1600)		+= gpio-blzp1600.o
 obj-$(CONFIG_GPIO_BRCMSTB)		+= gpio-brcmstb.o
 obj-$(CONFIG_GPIO_BT8XX)		+= gpio-bt8xx.o
+obj-$(CONFIG_GPIO_BY_PINCTRL)		+= gpio-by-pinctrl.o
 obj-$(CONFIG_GPIO_CADENCE)		+= gpio-cadence.o
 obj-$(CONFIG_GPIO_CGBC)			+= gpio-cgbc.o
 obj-$(CONFIG_GPIO_CLPS711X)		+= gpio-clps711x.o
drivers/gpio/gpio-by-pinctrl.c new file +124 -0

124 lines not on this page · raw message

Signature · 1 line
2.51.0
#13 lore raw
Quoted 2 lines · Dan Carpenter

The ARM SCMI pinctrl protocol allows GPIO access. Instead of creating a new SCMI gpio driver, this driver is a generic GPIO driver that uses

GPIO

Quoted 1 line

standard pinctrl interfaces.

...

drivers/gpio/Kconfig config GPIO_BRCMSTB · line 254

Quoted 6 lines
drivers/gpio/Kconfig +6 -0
+config GPIO_BY_PINCTRL
+	tristate "GPIO support based on a pure pin control backend"
+	depends on GPIOLIB
+	help
+	  Select this option to support GPIO devices based solely on pin
+	  control.  This is used to do GPIO over the ARM SCMI protocol.

This is not enough to understand (as discussion in previous round showed). Can we have added a Documentation/driver-api/gpio/... (to the existing one or a new one)?

...

Quoted 1 line

+// Copyright (C) 2023 Linaro Inc.

2026 (as well)?

...

+ errno.h // -ENOMEM, et cetera

drivers/gpio/gpio-by-pinctrl.c line 7

Quoted 3 lines
drivers/gpio/gpio-by-pinctrl.c new file +2 -0
+#include <linux/gpio/driver.h>
 
+#include <linux/list.h>

?! Cargo cult?

+ mod_devicetable.h // of_device_id

drivers/gpio/gpio-by-pinctrl.c line 11

Quoted 4 lines
drivers/gpio/gpio-by-pinctrl.c new file +4 -0
+#include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>

+ blank line.

Quoted 1 line

+#include "gpiolib.h"

...

drivers/gpio/gpio-by-pinctrl.c line 16

Quoted 3 lines
drivers/gpio/gpio-by-pinctrl.c new file +3 -0
+struct pin_control_gpio_priv {
+	struct gpio_chip chip;
+};

Unneeded, you can use struct gpio_chip directly. No?

...

Quoted 15 lines
drivers/gpio/gpio-by-pinctrl.c new file +15 -0
+static int pin_control_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
+{
+	unsigned long config;
+	bool in, out;
+	int ret;
+
+	config = PIN_CONFIG_INPUT_ENABLE;
+	ret = pinctrl_gpio_get_config(gc, offset, &config);
+	if (ret)
+		return ret;
+	in = config;
+
+	config = PIN_CONFIG_OUTPUT_ENABLE;
+	ret = pinctrl_gpio_get_config(gc, offset, &config);
+	if (ret)

drivers/gpio/gpio-by-pinctrl.c line 42

Quoted 10 lines
drivers/gpio/gpio-by-pinctrl.c new file +9 -0
+		return ret;
+	out = config;
 
+	/* Consistency check - in theory both can be enabled! */
+	if (in && !out)
+		return GPIO_LINE_DIRECTION_IN;
+	if (!in && out)
+		return GPIO_LINE_DIRECTION_OUT;
+
+	return -EINVAL;

When both are enabled it's out direction, so the entire piece can be simplified to

	if (out)
		return GPIO_LINE_DIRECTION_OUT;

	if (in)
		return GPIO_LINE_DIRECTION_IN;

	return ...something...; ideally it should be HiZ.

So, even more simplified will be just

	if (out)
		return GPIO_LINE_DIRECTION_OUT;
	else
		return GPIO_LINE_DIRECTION_IN;
Quoted 1 line

+}

...

drivers/gpio/gpio-by-pinctrl.c line 102

Quoted 5 lines
drivers/gpio/gpio-by-pinctrl.c new file +5 -0
+	ret = devm_gpiochip_add_data(dev, chip, priv);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, priv);

Not used.

drivers/gpio/gpio-by-pinctrl.c line 104

Quoted 1 line
drivers/gpio/gpio-by-pinctrl.c new file +1 -0
+	return 0;

Hence, the entire piece is just

	return devm_gpiochip_add_data(dev, chip, priv);
Signature · 2 lines
With Best Regards,
Andy Shevchenko