* [PATCH 01/11] pinctrl: scmi: send the drive strength in microamperes
2026-10-30 15:58 [PATCH 00/11] pinctrl: scmi: fixes and GPIO function support Clément Le Goffic
@ 2026-10-30 15:58 ` Clément Le Goffic
2026-10-30 15:58 ` [PATCH 02/11] pinctrl: scmi: map the schmitt trigger enable to its SCMI type Clément Le Goffic
` (9 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Clément Le Goffic @ 2026-10-30 15:58 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Linus Walleij, Peng Fan,
Oleksii Moisieiev, Andy Shevchenko, Dhruva Gole,
Bartosz Golaszewski
Cc: arm-scmi, linux-arm-kernel, linux-gpio, linux-kernel,
Clément Le Goffic
SCMI gives the drive strength in microamperes, but
PIN_CONFIG_DRIVE_STRENGTH is in milliamperes and was sent unchanged.
Convert it on set and on get. It is the only unit that differs: the
debounce is in microseconds and the pull resistances in ohms on both
sides, and every other value is a flag or implementation defined.
Fixes: eb524cb651b7 ("pinctrl: Implementation of the generic scmi-pinctrl driver")
Signed-off-by: Clément Le Goffic <clegoffic@baylibre.com>
---
drivers/pinctrl/pinctrl-scmi.c | 29 +++++++++++++++++++++++------
1 file changed, 23 insertions(+), 6 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c
index c93d61dfa282..6bc94c68e89a 100644
--- a/drivers/pinctrl/pinctrl-scmi.c
+++ b/drivers/pinctrl/pinctrl-scmi.c
@@ -14,6 +14,7 @@
#include <linux/scmi_protocol.h>
#include <linux/slab.h>
#include <linux/types.h>
+#include <linux/units.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinconf.h>
@@ -155,6 +156,15 @@ static int pinctrl_scmi_map_pinconf_type(enum pin_config_param param,
return 0;
}
+static u32 pinctrl_scmi_map_pinconf_arg_get(enum pin_config_param param,
+ u32 value)
+{
+ if (param == PIN_CONFIG_DRIVE_STRENGTH)
+ return value / MILLI;
+
+ return value;
+}
+
static int pinctrl_scmi_map_pinconf_type_get(enum pin_config_param param,
enum scmi_pinctrl_conf_type *type)
{
@@ -167,13 +177,17 @@ static int pinctrl_scmi_map_pinconf_type_get(enum pin_config_param param,
}
static int pinctrl_scmi_map_pinconf_type_set(enum pin_config_param param,
- enum scmi_pinctrl_conf_type *type)
+ enum scmi_pinctrl_conf_type *type,
+ u32 *arg)
{
if (param == PIN_CONFIG_LEVEL) {
*type = SCMI_PIN_OUTPUT_VALUE;
return 0;
}
+ if (param == PIN_CONFIG_DRIVE_STRENGTH)
+ *arg *= MILLI;
+
return pinctrl_scmi_map_pinconf_type(param, type);
}
@@ -203,6 +217,7 @@ static int pinctrl_scmi_pinconf_get(struct pinctrl_dev *pctldev,
if (ret)
return ret;
+ config_value = pinctrl_scmi_map_pinconf_arg_get(config_type, config_value);
*config = pinconf_to_config_packed(config_type, config_value);
return 0;
@@ -267,12 +282,13 @@ static int pinctrl_scmi_pinconf_set(struct pinctrl_dev *pctldev,
param = pinconf_to_config_param(configs[i]);
if (param == PIN_CONFIG_PERSIST_STATE)
continue;
- ret = pinctrl_scmi_map_pinconf_type_set(param, &p_config_type[cnt]);
+ p_config_value[cnt] = pinconf_to_config_argument(configs[i]);
+ ret = pinctrl_scmi_map_pinconf_type_set(param, &p_config_type[cnt],
+ &p_config_value[cnt]);
if (ret) {
dev_err(pmx->dev, "Error map pinconf_type %d\n", ret);
goto free_config;
}
- p_config_value[cnt] = pinconf_to_config_argument(configs[i]);
cnt++;
}
@@ -310,13 +326,13 @@ 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_set(param, &p_config_type[i]);
+ p_config_value[i] = pinconf_to_config_argument(configs[i]);
+ ret = pinctrl_scmi_map_pinconf_type_set(param, &p_config_type[i],
+ &p_config_value[i]);
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]);
}
ret = pinctrl_ops->settings_conf(pmx->ph, group, GROUP_TYPE,
@@ -359,6 +375,7 @@ static int pinctrl_scmi_pinconf_group_get(struct pinctrl_dev *pctldev,
if (ret)
return ret;
+ config_value = pinctrl_scmi_map_pinconf_arg_get(config_type, config_value);
*config = pinconf_to_config_packed(config_type, config_value);
return 0;
--
2.56.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 02/11] pinctrl: scmi: map the schmitt trigger enable to its SCMI type
2026-10-30 15:58 [PATCH 00/11] pinctrl: scmi: fixes and GPIO function support Clément Le Goffic
2026-10-30 15:58 ` [PATCH 01/11] pinctrl: scmi: send the drive strength in microamperes Clément Le Goffic
@ 2026-10-30 15:58 ` Clément Le Goffic
2026-10-30 15:58 ` [PATCH 03/11] pinctrl: scmi: send the settings without argument as enabled Clément Le Goffic
` (8 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Clément Le Goffic @ 2026-10-30 15:58 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Linus Walleij, Peng Fan,
Oleksii Moisieiev, Andy Shevchenko, Dhruva Gole,
Bartosz Golaszewski
Cc: arm-scmi, linux-arm-kernel, linux-gpio, linux-kernel,
Clément Le Goffic
PIN_CONFIG_INPUT_SCHMITT_ENABLE was sent as INPUT_MODE, which drives
the input buffer, and PIN_CONFIG_INPUT_SCHMITT, a threshold, as
INPUT_SCHMITT, which only takes 0 or 1. Send the enable as
INPUT_SCHMITT and refuse the threshold, the protocol has no type for
it.
Fixes: eb524cb651b7 ("pinctrl: Implementation of the generic scmi-pinctrl driver")
Signed-off-by: Clément Le Goffic <clegoffic@baylibre.com>
---
drivers/pinctrl/pinctrl-scmi.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c
index 6bc94c68e89a..5de47e060e8c 100644
--- a/drivers/pinctrl/pinctrl-scmi.c
+++ b/drivers/pinctrl/pinctrl-scmi.c
@@ -128,11 +128,8 @@ static int pinctrl_scmi_map_pinconf_type(enum pin_config_param param,
case PIN_CONFIG_INPUT_ENABLE:
*type = SCMI_PIN_INPUT_MODE;
break;
- case PIN_CONFIG_INPUT_SCHMITT:
- *type = SCMI_PIN_INPUT_SCHMITT;
- break;
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
- *type = SCMI_PIN_INPUT_MODE;
+ *type = SCMI_PIN_INPUT_SCHMITT;
break;
case PIN_CONFIG_MODE_LOW_POWER:
*type = SCMI_PIN_LOW_POWER_MODE;
--
2.56.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 03/11] pinctrl: scmi: send the settings without argument as enabled
2026-10-30 15:58 [PATCH 00/11] pinctrl: scmi: fixes and GPIO function support Clément Le Goffic
2026-10-30 15:58 ` [PATCH 01/11] pinctrl: scmi: send the drive strength in microamperes Clément Le Goffic
2026-10-30 15:58 ` [PATCH 02/11] pinctrl: scmi: map the schmitt trigger enable to its SCMI type Clément Le Goffic
@ 2026-10-30 15:58 ` Clément Le Goffic
2026-10-30 15:58 ` [PATCH 04/11] pinctrl: scmi: report an off setting as not set Clément Le Goffic
` (7 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Clément Le Goffic @ 2026-10-30 15:58 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Linus Walleij, Peng Fan,
Oleksii Moisieiev, Andy Shevchenko, Dhruva Gole,
Bartosz Golaszewski
Cc: arm-scmi, linux-arm-kernel, linux-gpio, linux-kernel,
Clément Le Goffic
bias-bus-hold, bias-disable, bias-high-impedance, drive-open-drain,
drive-open-source and drive-push-pull take no argument in Linux, so
they were sent with the value 0, which the protocol reads as disabled.
Send 1.
Fixes: eb524cb651b7 ("pinctrl: Implementation of the generic scmi-pinctrl driver")
Signed-off-by: Clément Le Goffic <clegoffic@baylibre.com>
---
drivers/pinctrl/pinctrl-scmi.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c
index 5de47e060e8c..f74ef0952ba9 100644
--- a/drivers/pinctrl/pinctrl-scmi.c
+++ b/drivers/pinctrl/pinctrl-scmi.c
@@ -173,6 +173,21 @@ static int pinctrl_scmi_map_pinconf_type_get(enum pin_config_param param,
return pinctrl_scmi_map_pinconf_type(param, type);
}
+static bool pinctrl_scmi_pinconf_arg_ignored(enum pin_config_param param)
+{
+ switch (param) {
+ case PIN_CONFIG_BIAS_BUS_HOLD:
+ case PIN_CONFIG_BIAS_DISABLE:
+ case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ case PIN_CONFIG_DRIVE_OPEN_SOURCE:
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ return true;
+ default:
+ return false;
+ }
+}
+
static int pinctrl_scmi_map_pinconf_type_set(enum pin_config_param param,
enum scmi_pinctrl_conf_type *type,
u32 *arg)
@@ -182,6 +197,9 @@ static int pinctrl_scmi_map_pinconf_type_set(enum pin_config_param param,
return 0;
}
+ if (pinctrl_scmi_pinconf_arg_ignored(param))
+ *arg = 1;
+
if (param == PIN_CONFIG_DRIVE_STRENGTH)
*arg *= MILLI;
--
2.56.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 04/11] pinctrl: scmi: report an off setting as not set
2026-10-30 15:58 [PATCH 00/11] pinctrl: scmi: fixes and GPIO function support Clément Le Goffic
` (2 preceding siblings ...)
2026-10-30 15:58 ` [PATCH 03/11] pinctrl: scmi: send the settings without argument as enabled Clément Le Goffic
@ 2026-10-30 15:58 ` Clément Le Goffic
2026-10-30 16:09 ` sashiko-bot
2026-10-30 15:58 ` [PATCH 05/11] firmware: arm_scmi: stop reading past PINCTRL_LIST_ASSOCIATIONS replies Clément Le Goffic
` (6 subsequent siblings)
10 siblings, 1 reply; 13+ messages in thread
From: Clément Le Goffic @ 2026-10-30 15:58 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Linus Walleij, Peng Fan,
Oleksii Moisieiev, Andy Shevchenko, Dhruva Gole,
Bartosz Golaszewski
Cc: arm-scmi, linux-arm-kernel, linux-gpio, linux-kernel,
Clément Le Goffic
A get of a setting that is on or off, the flags and the pulls, returned
0 as a value, so every one of them showed as set on every pin. Return
-EINVAL when the platform answers 0, which is how pinconf reports a
setting that is not active.
Fixes: eb524cb651b7 ("pinctrl: Implementation of the generic scmi-pinctrl driver")
Signed-off-by: Clément Le Goffic <clegoffic@baylibre.com>
---
drivers/pinctrl/pinctrl-scmi.c | 48 ++++++++++++++++++++++++++++++++++++------
1 file changed, 41 insertions(+), 7 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c
index f74ef0952ba9..355ad26cb215 100644
--- a/drivers/pinctrl/pinctrl-scmi.c
+++ b/drivers/pinctrl/pinctrl-scmi.c
@@ -153,13 +153,41 @@ static int pinctrl_scmi_map_pinconf_type(enum pin_config_param param,
return 0;
}
-static u32 pinctrl_scmi_map_pinconf_arg_get(enum pin_config_param param,
- u32 value)
+static bool pinctrl_scmi_pinconf_inactive_flag(enum pin_config_param param,
+ u32 value)
{
- if (param == PIN_CONFIG_DRIVE_STRENGTH)
- return value / MILLI;
+ if (value)
+ return false;
- return value;
+ switch (param) {
+ case PIN_CONFIG_BIAS_BUS_HOLD:
+ case PIN_CONFIG_BIAS_DISABLE:
+ case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
+ case PIN_CONFIG_BIAS_PULL_UP:
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ case PIN_CONFIG_DRIVE_OPEN_SOURCE:
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ case PIN_CONFIG_INPUT_ENABLE:
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static int pinctrl_scmi_map_pinconf_arg_get(enum pin_config_param param,
+ u32 *value)
+{
+ if (pinctrl_scmi_pinconf_inactive_flag(param, *value))
+ return -EINVAL;
+
+ if (param == PIN_CONFIG_DRIVE_STRENGTH)
+ *value /= MILLI;
+
+ return 0;
}
static int pinctrl_scmi_map_pinconf_type_get(enum pin_config_param param,
@@ -232,7 +260,10 @@ static int pinctrl_scmi_pinconf_get(struct pinctrl_dev *pctldev,
if (ret)
return ret;
- config_value = pinctrl_scmi_map_pinconf_arg_get(config_type, config_value);
+ ret = pinctrl_scmi_map_pinconf_arg_get(config_type, &config_value);
+ if (ret)
+ return ret;
+
*config = pinconf_to_config_packed(config_type, config_value);
return 0;
@@ -390,7 +421,10 @@ static int pinctrl_scmi_pinconf_group_get(struct pinctrl_dev *pctldev,
if (ret)
return ret;
- config_value = pinctrl_scmi_map_pinconf_arg_get(config_type, config_value);
+ ret = pinctrl_scmi_map_pinconf_arg_get(config_type, &config_value);
+ if (ret)
+ return ret;
+
*config = pinconf_to_config_packed(config_type, config_value);
return 0;
--
2.56.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH 04/11] pinctrl: scmi: report an off setting as not set
2026-10-30 15:58 ` [PATCH 04/11] pinctrl: scmi: report an off setting as not set Clément Le Goffic
@ 2026-10-30 16:09 ` sashiko-bot
0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-10-30 16:09 UTC (permalink / raw)
To: Clément Le Goffic; +Cc: linux-gpio
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] pinctrl: scmi: -EINVAL in pinctrl_scmi_pinconf_get() breaks GPIO get_direction
--
commit 925e342f7e0510b1b9dda63effb86ab92324b2e4
Author: Clément Le Goffic <clegoffic@baylibre.com>
pinctrl: scmi: report an off setting as not set
This commit changes the SCMI pinctrl driver to return -EINVAL when
querying boolean or pull pinconf parameters whose platform value is 0, so
that inactive settings are not reported as set.
> diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c
> index f74ef0952ba9b..355ad26cb2156 100644
> --- a/drivers/pinctrl/pinctrl-scmi.c
> +++ b/drivers/pinctrl/pinctrl-scmi.c
> @@ -153,13 +153,41 @@ static int pinctrl_scmi_map_pinconf_type(enum pin_config_param param,
> return 0;
> }
>
> -static u32 pinctrl_scmi_map_pinconf_arg_get(enum pin_config_param param,
> - u32 value)
> +static bool pinctrl_scmi_pinconf_inactive_flag(enum pin_config_param param,
> + u32 value)
> {
> + if (value)
> + return false;
> +
> + switch (param) {
> + case PIN_CONFIG_BIAS_BUS_HOLD:
> + case PIN_CONFIG_BIAS_DISABLE:
> + case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
> + case PIN_CONFIG_BIAS_PULL_DOWN:
> + case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
> + case PIN_CONFIG_BIAS_PULL_UP:
> + case PIN_CONFIG_DRIVE_OPEN_DRAIN:
> + case PIN_CONFIG_DRIVE_OPEN_SOURCE:
> + case PIN_CONFIG_DRIVE_PUSH_PULL:
> + case PIN_CONFIG_INPUT_ENABLE:
> + case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
> + case PIN_CONFIG_OUTPUT_ENABLE:
> + return true;
> + default:
> + return false;
> + }
> +}
> +
> +static int pinctrl_scmi_map_pinconf_arg_get(enum pin_config_param param,
> + u32 *value)
> +{
> + if (pinctrl_scmi_pinconf_inactive_flag(param, *value))
> + return -EINVAL;
> +
> if (param == PIN_CONFIG_DRIVE_STRENGTH)
> - return value / MILLI;
> + *value /= MILLI;
>
> - return value;
> + return 0;
> }
>
> static int pinctrl_scmi_map_pinconf_type_get(enum pin_config_param param,
> @@ -232,7 +260,10 @@ static int pinctrl_scmi_pinconf_get(struct pinctrl_dev *pctldev,
> if (ret)
> return ret;
>
> - config_value = pinctrl_scmi_map_pinconf_arg_get(config_type, config_value);
> + ret = pinctrl_scmi_map_pinconf_arg_get(config_type, &config_value);
> + if (ret)
> + return ret;
[Severity: High]
Does returning -EINVAL for PIN_CONFIG_OUTPUT_ENABLE when config_value is 0
break pin_control_gpio_get_direction() in drivers/gpio/gpio-by-pinctrl.c
for scmi-pinctrl-gpio?
In drivers/gpio/gpio-by-pinctrl.c, pin_control_gpio_get_direction()
queries the pin direction through pinctrl_gpio_get_config() ->
pin_config_get_for_pin() -> pinctrl_scmi_pinconf_get():
drivers/gpio/gpio-by-pinctrl.c:pin_control_gpio_get_direction() {
config = PIN_CONFIG_OUTPUT_ENABLE;
ret = pinctrl_gpio_get_config(gc, offset, &config);
if (ret)
return ret;
if (config)
return GPIO_LINE_DIRECTION_OUT;
return GPIO_LINE_DIRECTION_IN;
}
When a pin has output mode disabled (SCMI_PIN_OUTPUT_MODE is 0, meaning
the pin is an input), pinctrl_scmi_pinconf_inactive_flag() now returns
true for PIN_CONFIG_OUTPUT_ENABLE, so pinctrl_scmi_pinconf_get() returns
-EINVAL.
Because pin_control_gpio_get_direction() returns ret immediately when it
is non-zero, querying the direction of any input line via
gpiod_get_direction() or gpiochip_lock_as_irq() will fail with -EINVAL,
and GPIO_LINE_DIRECTION_IN becomes unreachable.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261030-clegoffic-pinctrl-scmi-gpio-v1-0-52d92843ad97@baylibre.com?part=4
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 05/11] firmware: arm_scmi: stop reading past PINCTRL_LIST_ASSOCIATIONS replies
2026-10-30 15:58 [PATCH 00/11] pinctrl: scmi: fixes and GPIO function support Clément Le Goffic
` (3 preceding siblings ...)
2026-10-30 15:58 ` [PATCH 04/11] pinctrl: scmi: report an off setting as not set Clément Le Goffic
@ 2026-10-30 15:58 ` Clément Le Goffic
2026-10-30 15:58 ` [PATCH 06/11] firmware: arm_scmi: report the pin-only and GPIO flags of functions Clément Le Goffic
` (5 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Clément Le Goffic @ 2026-10-30 15:58 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Linus Walleij, Peng Fan,
Oleksii Moisieiev, Andy Shevchenko, Dhruva Gole,
Bartosz Golaszewski
Cc: arm-scmi, linux-arm-kernel, linux-gpio, linux-kernel,
Clément Le Goffic
The transport cuts a reply larger than the receive buffer, but the iterator
still reads every identifier the reply announces. Use only the identifiers
that were copied and ask again for the others.
Fixes: 2145af01b9cb ("firmware: arm_scmi: Add basic support for SCMI v3.2 pincontrol protocol")
Signed-off-by: Clément Le Goffic <clegoffic@baylibre.com>
---
drivers/firmware/arm_scmi/pinctrl.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/firmware/arm_scmi/pinctrl.c b/drivers/firmware/arm_scmi/pinctrl.c
index 42cb1aef1fe1..69645ce73d9d 100644
--- a/drivers/firmware/arm_scmi/pinctrl.c
+++ b/drivers/firmware/arm_scmi/pinctrl.c
@@ -261,10 +261,22 @@ static int iter_pinctrl_assoc_update_state(struct scmi_iterator_state *st,
const void *response, void *priv)
{
const struct scmi_resp_pinctrl_list_assoc *r = response;
+ unsigned int nr_fit = 0;
st->num_returned = RETURNED(r->flags);
st->num_remaining = REMAINING(r->flags);
+ if (st->rx_len > sizeof(*r))
+ nr_fit = (st->rx_len - sizeof(*r)) / sizeof(r->array[0]);
+
+ if (st->num_returned > nr_fit) {
+ if (!nr_fit)
+ return -EPROTO;
+
+ st->num_remaining += st->num_returned - nr_fit;
+ st->num_returned = nr_fit;
+ }
+
return 0;
}
--
2.56.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 06/11] firmware: arm_scmi: report the pin-only and GPIO flags of functions
2026-10-30 15:58 [PATCH 00/11] pinctrl: scmi: fixes and GPIO function support Clément Le Goffic
` (4 preceding siblings ...)
2026-10-30 15:58 ` [PATCH 05/11] firmware: arm_scmi: stop reading past PINCTRL_LIST_ASSOCIATIONS replies Clément Le Goffic
@ 2026-10-30 15:58 ` Clément Le Goffic
2026-10-30 15:58 ` [PATCH 07/11] pinctrl: scmi: give no groups to pin-only functions Clément Le Goffic
` (4 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Clément Le Goffic @ 2026-10-30 15:58 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Linus Walleij, Peng Fan,
Oleksii Moisieiev, Andy Shevchenko, Dhruva Gole,
Bartosz Golaszewski
Cc: arm-scmi, linux-arm-kernel, linux-gpio, linux-kernel,
Clément Le Goffic
Keep the pin-only and GPIO flags that PINCTRL_ATTRIBUTES returns for a
function, and add a function_flags_get operation to read them.
Signed-off-by: Clément Le Goffic <clegoffic@baylibre.com>
---
drivers/firmware/arm_scmi/pinctrl.c | 43 ++++++++++++++++++++++++++++++++-----
include/linux/scmi_protocol.h | 6 +++++-
2 files changed, 43 insertions(+), 6 deletions(-)
diff --git a/drivers/firmware/arm_scmi/pinctrl.c b/drivers/firmware/arm_scmi/pinctrl.c
index 69645ce73d9d..ba602242754c 100644
--- a/drivers/firmware/arm_scmi/pinctrl.c
+++ b/drivers/firmware/arm_scmi/pinctrl.c
@@ -27,6 +27,8 @@
#define GET_FUNCTIONS_NR(x) le32_get_bits((x), GENMASK(15, 0))
#define EXT_NAME_FLAG(x) le32_get_bits((x), BIT(31))
+#define GPIO_FUNC(x) le32_get_bits((x), BIT(17))
+#define PIN_ONLY_FUNC(x) le32_get_bits((x), BIT(16))
#define NUM_ELEMS(x) le32_get_bits((x), GENMASK(15, 0))
#define REMAINING(x) le32_get_bits((x), GENMASK(31, 16))
@@ -107,6 +109,8 @@ struct scmi_group_info {
struct scmi_function_info {
char name[SCMI_MAX_STR_SIZE];
bool present;
+ bool pin_only;
+ bool gpio;
u32 *groups;
u32 nr_groups;
};
@@ -188,8 +192,8 @@ static int scmi_pinctrl_validate_id(const struct scmi_protocol_handle *ph,
static int scmi_pinctrl_attributes(const struct scmi_protocol_handle *ph,
enum scmi_pinctrl_selector_type type,
- u32 selector, char *name,
- u32 *n_elems)
+ u32 selector, char *name, u32 *n_elems,
+ bool *pin_only, bool *gpio)
{
int ret;
struct scmi_xfer *t;
@@ -219,6 +223,12 @@ static int scmi_pinctrl_attributes(const struct scmi_protocol_handle *ph,
if (n_elems)
*n_elems = NUM_ELEMS(rx->attributes);
+ if (pin_only)
+ *pin_only = PIN_ONLY_FUNC(rx->attributes);
+
+ if (gpio)
+ *gpio = GPIO_FUNC(rx->attributes);
+
strscpy(name, rx->name, SCMI_SHORT_NAME_MAX_SIZE);
ext_name_flag = !!EXT_NAME_FLAG(rx->attributes);
@@ -623,7 +633,7 @@ static int scmi_pinctrl_get_group_info(const struct scmi_protocol_handle *ph,
return 0;
ret = scmi_pinctrl_attributes(ph, GROUP_TYPE, selector, group->name,
- &group->nr_pins);
+ &group->nr_pins, NULL, NULL);
if (ret)
return ret;
@@ -702,7 +712,8 @@ static int scmi_pinctrl_get_function_info(const struct scmi_protocol_handle *ph,
return 0;
ret = scmi_pinctrl_attributes(ph, FUNCTION_TYPE, selector, func->name,
- &func->nr_groups);
+ &func->nr_groups, &func->pin_only,
+ &func->gpio);
if (ret)
return ret;
@@ -765,6 +776,26 @@ scmi_pinctrl_function_groups_get(const struct scmi_protocol_handle *ph,
return 0;
}
+static int
+scmi_pinctrl_function_flags_get(const struct scmi_protocol_handle *ph,
+ u32 selector, bool *pin_only, bool *gpio)
+{
+ struct scmi_pinctrl_info *pi = ph->get_priv(ph);
+ int ret;
+
+ if (!pin_only || !gpio)
+ return -EINVAL;
+
+ ret = scmi_pinctrl_get_function_info(ph, selector);
+ if (ret)
+ return ret;
+
+ *pin_only = pi->functions[selector].pin_only;
+ *gpio = pi->functions[selector].gpio;
+
+ return 0;
+}
+
static int scmi_pinctrl_mux_set(const struct scmi_protocol_handle *ph,
u32 selector, u32 group)
{
@@ -785,7 +816,8 @@ static int scmi_pinctrl_get_pin_info(const struct scmi_protocol_handle *ph,
if (pin->present)
return 0;
- ret = scmi_pinctrl_attributes(ph, PIN_TYPE, selector, pin->name, NULL);
+ ret = scmi_pinctrl_attributes(ph, PIN_TYPE, selector, pin->name, NULL,
+ NULL, NULL);
if (ret)
return ret;
@@ -833,6 +865,7 @@ static const struct scmi_pinctrl_proto_ops pinctrl_proto_ops = {
.name_get = scmi_pinctrl_name_get,
.group_pins_get = scmi_pinctrl_group_pins_get,
.function_groups_get = scmi_pinctrl_function_groups_get,
+ .function_flags_get = scmi_pinctrl_function_flags_get,
.mux_set = scmi_pinctrl_mux_set,
.settings_get_one = scmi_pinctrl_settings_get_one,
.settings_get_all = scmi_pinctrl_settings_get_all,
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 3f7cc35eb861..072190e89064 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -785,7 +785,9 @@ enum scmi_pinctrl_conf_type {
* @name_get: returns name by index of given type
* @group_pins_get: returns the set of pins, assigned to the specified group
* @function_groups_get: returns the set of groups, assigned to the specified
- * function
+ * function, or the set of pins for a pin-only function
+ * @function_flags_get: tells whether the specified function is pin-only and
+ * whether it is a GPIO function
* @mux_set: set muxing function for groups of pins
* @settings_get_one: returns one configuration parameter for pin or group
* specified by config_type
@@ -806,6 +808,8 @@ struct scmi_pinctrl_proto_ops {
int (*function_groups_get)(const struct scmi_protocol_handle *ph,
u32 selector, unsigned int *nr_groups,
const unsigned int **groups);
+ int (*function_flags_get)(const struct scmi_protocol_handle *ph,
+ u32 selector, bool *pin_only, bool *gpio);
int (*mux_set)(const struct scmi_protocol_handle *ph, u32 selector,
u32 group);
int (*settings_get_one)(const struct scmi_protocol_handle *ph,
--
2.56.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 07/11] pinctrl: scmi: give no groups to pin-only functions
2026-10-30 15:58 [PATCH 00/11] pinctrl: scmi: fixes and GPIO function support Clément Le Goffic
` (5 preceding siblings ...)
2026-10-30 15:58 ` [PATCH 06/11] firmware: arm_scmi: report the pin-only and GPIO flags of functions Clément Le Goffic
@ 2026-10-30 15:58 ` Clément Le Goffic
2026-10-30 15:58 ` [PATCH 08/11] pinctrl: scmi: mark the GPIO functions Clément Le Goffic
` (3 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Clément Le Goffic @ 2026-10-30 15:58 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Linus Walleij, Peng Fan,
Oleksii Moisieiev, Andy Shevchenko, Dhruva Gole,
Bartosz Golaszewski
Cc: arm-scmi, linux-arm-kernel, linux-gpio, linux-kernel,
Clément Le Goffic
For a pin-only function PINCTRL_LIST_ASSOCIATIONS returns pins, but the
driver registered them as groups. Register pin-only functions without
groups.
Fixes: eb524cb651b7 ("pinctrl: Implementation of the generic scmi-pinctrl driver")
Signed-off-by: Clément Le Goffic <clegoffic@baylibre.com>
---
drivers/pinctrl/pinctrl-scmi.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c
index 355ad26cb215..1a14e254f011 100644
--- a/drivers/pinctrl/pinctrl-scmi.c
+++ b/drivers/pinctrl/pinctrl-scmi.c
@@ -443,6 +443,7 @@ static int pinctrl_scmi_get_functions(struct scmi_pinctrl *pmx)
{
unsigned int nr_funcs, nr_groups, i, j;
const unsigned int *group_ids;
+ bool pin_only, gpio;
const char *fname;
const char **gnames;
int ret;
@@ -455,13 +456,20 @@ static int pinctrl_scmi_get_functions(struct scmi_pinctrl *pmx)
if (ret)
return ret;
+ ret = pinctrl_ops->function_flags_get(pmx->ph, i, &pin_only,
+ &gpio);
+ if (ret)
+ return ret;
+
ret = pinctrl_ops->function_groups_get(pmx->ph, i,
&nr_groups,
&group_ids);
if (ret)
return ret;
- if (!nr_groups)
+ if (pin_only)
+ nr_groups = 0;
+ else if (!nr_groups)
dev_warn(pmx->dev,
"Function %s contains no groups\n",
fname);
--
2.56.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 08/11] pinctrl: scmi: mark the GPIO functions
2026-10-30 15:58 [PATCH 00/11] pinctrl: scmi: fixes and GPIO function support Clément Le Goffic
` (6 preceding siblings ...)
2026-10-30 15:58 ` [PATCH 07/11] pinctrl: scmi: give no groups to pin-only functions Clément Le Goffic
@ 2026-10-30 15:58 ` Clément Le Goffic
2026-10-30 15:58 ` [PATCH 09/11] pinctrl: scmi: report whether a function is GPIO Clément Le Goffic
` (2 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Clément Le Goffic @ 2026-10-30 15:58 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Linus Walleij, Peng Fan,
Oleksii Moisieiev, Andy Shevchenko, Dhruva Gole,
Bartosz Golaszewski
Cc: arm-scmi, linux-arm-kernel, linux-gpio, linux-kernel,
Clément Le Goffic
Register the functions flagged as GPIO with PINFUNCTION_FLAG_GPIO.
Signed-off-by: Clément Le Goffic <clegoffic@baylibre.com>
---
drivers/pinctrl/pinctrl-scmi.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c
index 1a14e254f011..24e02de543ca 100644
--- a/drivers/pinctrl/pinctrl-scmi.c
+++ b/drivers/pinctrl/pinctrl-scmi.c
@@ -443,6 +443,7 @@ static int pinctrl_scmi_get_functions(struct scmi_pinctrl *pmx)
{
unsigned int nr_funcs, nr_groups, i, j;
const unsigned int *group_ids;
+ struct pinfunction func;
bool pin_only, gpio;
const char *fname;
const char **gnames;
@@ -486,8 +487,12 @@ static int pinctrl_scmi_get_functions(struct scmi_pinctrl *pmx)
return ret;
}
- ret = pinmux_generic_add_function(pmx->pctldev, fname, gnames,
- nr_groups, NULL);
+ if (gpio)
+ func = PINCTRL_GPIO_PINFUNCTION(fname, gnames, nr_groups);
+ else
+ func = PINCTRL_PINFUNCTION(fname, gnames, nr_groups);
+
+ ret = pinmux_generic_add_pinfunction(pmx->pctldev, &func, NULL);
if (ret < 0)
return ret;
if (ret != i) {
--
2.56.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 09/11] pinctrl: scmi: report whether a function is GPIO
2026-10-30 15:58 [PATCH 00/11] pinctrl: scmi: fixes and GPIO function support Clément Le Goffic
` (7 preceding siblings ...)
2026-10-30 15:58 ` [PATCH 08/11] pinctrl: scmi: mark the GPIO functions Clément Le Goffic
@ 2026-10-30 15:58 ` Clément Le Goffic
2026-10-30 15:58 ` [PATCH 10/11] firmware: arm_scmi: add an operation to set the function of a single pin Clément Le Goffic
2026-10-30 15:58 ` [PATCH 11/11] pinctrl: scmi: select the GPIO function on GPIO requests Clément Le Goffic
10 siblings, 0 replies; 13+ messages in thread
From: Clément Le Goffic @ 2026-10-30 15:58 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Linus Walleij, Peng Fan,
Oleksii Moisieiev, Andy Shevchenko, Dhruva Gole,
Bartosz Golaszewski
Cc: arm-scmi, linux-arm-kernel, linux-gpio, linux-kernel,
Clément Le Goffic
Use pinmux_generic_function_is_gpio() for the function_is_gpio
operation.
Signed-off-by: Clément Le Goffic <clegoffic@baylibre.com>
---
drivers/pinctrl/pinctrl-scmi.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c
index 24e02de543ca..6f44e8c0fee6 100644
--- a/drivers/pinctrl/pinctrl-scmi.c
+++ b/drivers/pinctrl/pinctrl-scmi.c
@@ -80,6 +80,7 @@ static const struct pinmux_ops pinctrl_scmi_pinmux_ops = {
.get_functions_count = pinmux_generic_get_function_count,
.get_function_name = pinmux_generic_get_function_name,
.get_function_groups = pinmux_generic_get_function_groups,
+ .function_is_gpio = pinmux_generic_function_is_gpio,
.set_mux = pinctrl_scmi_func_set_mux,
};
--
2.56.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 10/11] firmware: arm_scmi: add an operation to set the function of a single pin
2026-10-30 15:58 [PATCH 00/11] pinctrl: scmi: fixes and GPIO function support Clément Le Goffic
` (8 preceding siblings ...)
2026-10-30 15:58 ` [PATCH 09/11] pinctrl: scmi: report whether a function is GPIO Clément Le Goffic
@ 2026-10-30 15:58 ` Clément Le Goffic
2026-10-30 15:58 ` [PATCH 11/11] pinctrl: scmi: select the GPIO function on GPIO requests Clément Le Goffic
10 siblings, 0 replies; 13+ messages in thread
From: Clément Le Goffic @ 2026-10-30 15:58 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Linus Walleij, Peng Fan,
Oleksii Moisieiev, Andy Shevchenko, Dhruva Gole,
Bartosz Golaszewski
Cc: arm-scmi, linux-arm-kernel, linux-gpio, linux-kernel,
Clément Le Goffic
Add pin_mux_set, which selects a function on a single pin. mux_set only
works on groups.
Signed-off-by: Clément Le Goffic <clegoffic@baylibre.com>
---
drivers/firmware/arm_scmi/pinctrl.c | 7 +++++++
include/linux/scmi_protocol.h | 3 +++
2 files changed, 10 insertions(+)
diff --git a/drivers/firmware/arm_scmi/pinctrl.c b/drivers/firmware/arm_scmi/pinctrl.c
index ba602242754c..27b9a38ede74 100644
--- a/drivers/firmware/arm_scmi/pinctrl.c
+++ b/drivers/firmware/arm_scmi/pinctrl.c
@@ -802,6 +802,12 @@ static int scmi_pinctrl_mux_set(const struct scmi_protocol_handle *ph,
return scmi_pinctrl_function_select(ph, group, GROUP_TYPE, selector);
}
+static int scmi_pinctrl_pin_mux_set(const struct scmi_protocol_handle *ph,
+ u32 selector, u32 pin)
+{
+ return scmi_pinctrl_function_select(ph, pin, PIN_TYPE, selector);
+}
+
static int scmi_pinctrl_get_pin_info(const struct scmi_protocol_handle *ph,
u32 selector)
{
@@ -867,6 +873,7 @@ static const struct scmi_pinctrl_proto_ops pinctrl_proto_ops = {
.function_groups_get = scmi_pinctrl_function_groups_get,
.function_flags_get = scmi_pinctrl_function_flags_get,
.mux_set = scmi_pinctrl_mux_set,
+ .pin_mux_set = scmi_pinctrl_pin_mux_set,
.settings_get_one = scmi_pinctrl_settings_get_one,
.settings_get_all = scmi_pinctrl_settings_get_all,
.settings_conf = scmi_pinctrl_settings_conf,
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 072190e89064..736d34968f42 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -789,6 +789,7 @@ enum scmi_pinctrl_conf_type {
* @function_flags_get: tells whether the specified function is pin-only and
* whether it is a GPIO function
* @mux_set: set muxing function for groups of pins
+ * @pin_mux_set: set muxing function for a single pin
* @settings_get_one: returns one configuration parameter for pin or group
* specified by config_type
* @settings_get_all: returns all configuration parameters for pin or group
@@ -812,6 +813,8 @@ struct scmi_pinctrl_proto_ops {
u32 selector, bool *pin_only, bool *gpio);
int (*mux_set)(const struct scmi_protocol_handle *ph, u32 selector,
u32 group);
+ int (*pin_mux_set)(const struct scmi_protocol_handle *ph, u32 selector,
+ u32 pin);
int (*settings_get_one)(const struct scmi_protocol_handle *ph,
u32 selector,
enum scmi_pinctrl_selector_type type,
--
2.56.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 11/11] pinctrl: scmi: select the GPIO function on GPIO requests
2026-10-30 15:58 [PATCH 00/11] pinctrl: scmi: fixes and GPIO function support Clément Le Goffic
` (9 preceding siblings ...)
2026-10-30 15:58 ` [PATCH 10/11] firmware: arm_scmi: add an operation to set the function of a single pin Clément Le Goffic
@ 2026-10-30 15:58 ` Clément Le Goffic
10 siblings, 0 replies; 13+ messages in thread
From: Clément Le Goffic @ 2026-10-30 15:58 UTC (permalink / raw)
To: Sudeep Holla, Cristian Marussi, Linus Walleij, Peng Fan,
Oleksii Moisieiev, Andy Shevchenko, Dhruva Gole,
Bartosz Golaszewski
Cc: arm-scmi, linux-arm-kernel, linux-gpio, linux-kernel,
Clément Le Goffic
On a GPIO request, select the GPIO function of the pin, on the pin for a
pin-only function or on its single-pin group. Without a GPIO function the
mux is left as it is.
Signed-off-by: Clément Le Goffic <clegoffic@baylibre.com>
---
drivers/pinctrl/pinctrl-scmi.c | 64 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c
index 6f44e8c0fee6..ba649304638e 100644
--- a/drivers/pinctrl/pinctrl-scmi.c
+++ b/drivers/pinctrl/pinctrl-scmi.c
@@ -74,6 +74,69 @@ static int pinctrl_scmi_free(struct pinctrl_dev *pctldev, unsigned int offset)
return pinctrl_ops->pin_free(pmx->ph, offset);
}
+static int pinctrl_scmi_gpio_mux_set(struct scmi_pinctrl *pmx, unsigned int pin)
+{
+ const unsigned int *elems, *pins;
+ unsigned int nr_elems, nr_pins, i;
+ bool pin_only, gpio;
+ int nr_functions, func, ret;
+
+ nr_functions = pinctrl_ops->count_get(pmx->ph, FUNCTION_TYPE);
+ for (func = 0; func < nr_functions; func++) {
+ ret = pinctrl_ops->function_flags_get(pmx->ph, func, &pin_only,
+ &gpio);
+ if (ret)
+ return ret;
+
+ if (!gpio)
+ continue;
+
+ ret = pinctrl_ops->function_groups_get(pmx->ph, func, &nr_elems,
+ &elems);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < nr_elems; i++) {
+ if (pin_only) {
+ if (elems[i] != pin)
+ continue;
+
+ return pinctrl_ops->pin_mux_set(pmx->ph, func,
+ pin);
+ }
+
+ ret = pinctrl_ops->group_pins_get(pmx->ph, elems[i],
+ &pins, &nr_pins);
+ if (ret)
+ return ret;
+
+ if (nr_pins == 1 && pins[0] == pin)
+ return pinctrl_ops->mux_set(pmx->ph, func,
+ elems[i]);
+ }
+ }
+
+ return 0;
+}
+
+static int pinctrl_scmi_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset)
+{
+ struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
+ int ret;
+
+ ret = pinctrl_ops->pin_request(pmx->ph, offset);
+ if (ret)
+ return ret;
+
+ ret = pinctrl_scmi_gpio_mux_set(pmx, offset);
+ if (ret)
+ pinctrl_ops->pin_free(pmx->ph, offset);
+
+ return ret;
+}
+
static const struct pinmux_ops pinctrl_scmi_pinmux_ops = {
.request = pinctrl_scmi_request,
.free = pinctrl_scmi_free,
@@ -82,6 +145,7 @@ static const struct pinmux_ops pinctrl_scmi_pinmux_ops = {
.get_function_groups = pinmux_generic_get_function_groups,
.function_is_gpio = pinmux_generic_function_is_gpio,
.set_mux = pinctrl_scmi_func_set_mux,
+ .gpio_request_enable = pinctrl_scmi_gpio_request_enable,
};
static int pinctrl_scmi_map_pinconf_type(enum pin_config_param param,
--
2.56.0
^ permalink raw reply related [flat|nested] 13+ messages in thread