From: Yixun Lan <dlan@kernel.org>
To: u-boot-spacemit@groups.io, u-boot@lists.u-boot-project.org
Cc: Eric Chung <eric.chung@riscstar.com>,
Raymond Mao <raymond.mao@riscstar.com>,
Junhui Liu <junhui.liu@pigmoral.tech>,
Tom Rini <trini@konsulko.com>, Yixun Lan <dlan@kernel.org>
Subject: [PATCH v2 1/2] pinctrl: spacemit: configure drive strength based on power source
Date: Wed, 23 Sep 2026 13:06:52 +0000 [thread overview]
Message-ID: <20260923-01-k3-pinctrl-support-v2-1-e76a917ee252@kernel.org> (raw)
In-Reply-To: <20260923-01-k3-pinctrl-support-v2-0-e76a917ee252@kernel.org>
SpacemiT external-voltage pins use different drive strength tables for
1.8V and 3.3V. The selected power source therefore needs to be known
before programming the drive strength. But pinctrl_generic_set_state()
applies pin configuration properties according device tree order, which
lead to configure drive-strength before power-source.
Add a vendor specific set_state() callback that applies the supported
properties in a fixed order, ensuring that power-source is configured
before setting drive strength.
Signed-off-by: Yixun Lan <dlan@kernel.org>
---
drivers/pinctrl/spacemit/pinctrl-k1.c | 166 +++++++++++++++++++++++++++-------
1 file changed, 131 insertions(+), 35 deletions(-)
diff --git a/drivers/pinctrl/spacemit/pinctrl-k1.c b/drivers/pinctrl/spacemit/pinctrl-k1.c
index 7d801f08d20..ff0fa3a4b18 100644
--- a/drivers/pinctrl/spacemit/pinctrl-k1.c
+++ b/drivers/pinctrl/spacemit/pinctrl-k1.c
@@ -441,8 +441,8 @@ static const struct pinconf_param spacemit_pinconf_params[] = {
{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
- { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, U32_MAX },
{ "power-source", PIN_CONFIG_POWER_SOURCE, U32_MAX },
+ { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, U32_MAX },
};
static void spacemit_set_io_power_domain(struct udevice *dev,
@@ -474,17 +474,60 @@ static void spacemit_set_io_power_domain(struct udevice *dev,
writel(val, priv->regs + IO_PWR_DOMAIN_OFFSET + offset);
}
+static enum spacemit_pin_io_type spacemit_get_pin_io_type(struct spacemit_pinctrl_priv *priv,
+ unsigned int pin)
+{
+ int i;
+
+ for (i = 0; i < priv->nr_io_pins; i++)
+ if (priv->io_pins[i].pin == pin &&
+ priv->io_pins[i].io_type != IO_TYPE_EXTERNAL)
+ return priv->io_pins[i].io_type;
+
+ return IO_TYPE_1V8;
+}
+
+static int spacemit_set_pin_power_source(struct udevice *dev, unsigned int pin,
+ unsigned int power_source)
+{
+ struct spacemit_pinctrl_priv *priv = dev_get_priv(dev);
+ enum spacemit_pin_io_type io_type;
+ int i;
+
+ switch (power_source) {
+ case PIN_POWER_STATE_1V8:
+ io_type = IO_TYPE_1V8;
+ break;
+ case PIN_POWER_STATE_3V3:
+ io_type = IO_TYPE_3V3;
+ break;
+ default:
+ dev_err(dev, "Invalid power source (%d)\n", power_source);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < priv->nr_io_pins; i++) {
+ if (priv->io_pins[i].pin != pin)
+ continue;
+
+ priv->io_pins[i].io_type = io_type;
+ spacemit_set_io_power_domain(dev, pin, io_type);
+
+ return 0;
+ }
+
+ return 0;
+}
+
static int spacemit_pinconf_set(struct udevice *dev, unsigned int pin_selector,
unsigned int param, unsigned int argument)
{
- struct spacemit_pinctrl_data *data;
struct spacemit_pinctrl_priv *priv = dev_get_priv(dev);
+ struct spacemit_pinctrl_data *data;
+ enum spacemit_pin_io_type io_type;
void __iomem *addr;
u32 mask;
- unsigned int io_type;
u8 ds;
- bool found;
- int i;
data = (struct spacemit_pinctrl_data *)dev_get_driver_data(dev);
if (!data || !data->pin_to_reg)
@@ -504,14 +547,7 @@ static int spacemit_pinconf_set(struct udevice *dev, unsigned int pin_selector,
clrsetbits_le32(addr, mask, PAD_PULLUP | PAD_PULL_EN);
break;
case PIN_CONFIG_DRIVE_STRENGTH:
- io_type = IO_TYPE_1V8;
- for (i = 0; i < priv->nr_io_pins; i++) {
- if (priv->io_pins[i].pin != pin_selector)
- continue;
- if (priv->io_pins[i].io_type != IO_TYPE_EXTERNAL)
- io_type = priv->io_pins[i].io_type;
- break;
- }
+ io_type = spacemit_get_pin_io_type(priv, pin_selector);
if (io_type != IO_TYPE_3V3 && io_type != IO_TYPE_1V8) {
dev_err(dev, "Invalid IO type (%d)\n", io_type);
return -EINVAL;
@@ -520,30 +556,90 @@ static int spacemit_pinconf_set(struct udevice *dev, unsigned int pin_selector,
clrsetbits_le32(addr, PAD_DRIVE, FIELD_PREP(PAD_DRIVE, ds));
break;
case PIN_CONFIG_POWER_SOURCE:
- for (i = 0, found = false; i < priv->nr_io_pins; i++) {
- if (priv->io_pins[i].pin != pin_selector)
- continue;
- if (argument == PIN_POWER_STATE_3V3) {
- priv->io_pins[i].io_type = IO_TYPE_3V3;
- found = true;
- } else if (argument == PIN_POWER_STATE_1V8) {
- priv->io_pins[i].io_type = IO_TYPE_1V8;
- found = true;
- }
- break;
- }
- if (!found && argument != PIN_POWER_STATE_1V8 &&
- argument != PIN_POWER_STATE_3V3) {
- dev_err(dev, "Invalid power source (%d)\n", argument);
- return -EINVAL;
- }
- if (found)
- spacemit_set_io_power_domain(dev, pin_selector,
- priv->io_pins[i].io_type);
- break;
+ return spacemit_set_pin_power_source(dev, pin_selector, argument);
default:
return -EOPNOTSUPP;
}
+
+ return 0;
+}
+
+static int spacemit_pinctrl_apply_group(struct udevice *dev,
+ struct udevice *config)
+{
+ const struct pinconf_param *param;
+ const void *value;
+ u32 argument;
+ u32 pinmux;
+ int npins;
+ int len;
+ int ret;
+ int i, j;
+
+ ret = dev_read_size(config, "pinmux");
+ if (ret == -EINVAL)
+ return 0;
+ if (ret < 0 || ret % sizeof(pinmux))
+ return -EINVAL;
+ npins = ret / sizeof(pinmux);
+
+ for (i = 0; i < npins; i++) {
+ ret = dev_read_u32_index(config, "pinmux", i, &pinmux);
+ if (ret)
+ return ret;
+
+ ret = spacemit_pinmux_set(dev, spacemit_dt_get_pin(pinmux),
+ spacemit_dt_get_pin_mux(pinmux));
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(spacemit_pinconf_params); i++) {
+ param = &spacemit_pinconf_params[i];
+ value = dev_read_prop(config, param->property, &len);
+ if (!value)
+ continue;
+
+ if (len >= sizeof(fdt32_t))
+ argument = fdt32_to_cpu(*(const fdt32_t *)value);
+ else
+ argument = param->default_value;
+
+ for (j = 0; j < npins; j++) {
+ ret = dev_read_u32_index(config, "pinmux", j,
+ &pinmux);
+ if (ret)
+ return ret;
+
+ ret = spacemit_pinconf_set(dev,
+ spacemit_dt_get_pin(pinmux),
+ param->param, argument);
+ if (ret)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int spacemit_pinctrl_set_state(struct udevice *dev,
+ struct udevice *config)
+{
+ struct udevice *child;
+ int ret;
+
+ ret = spacemit_pinctrl_apply_group(dev, config);
+ if (ret)
+ return ret;
+
+ for (device_find_first_child(config, &child);
+ child;
+ device_find_next_child(&child)) {
+ ret = spacemit_pinctrl_apply_group(dev, child);
+ if (ret)
+ return ret;
+ }
+
return 0;
}
@@ -625,7 +721,7 @@ static const struct pinctrl_ops spacemit_pinctrl_ops = {
.get_pin_name = spacemit_get_pin_name,
.get_functions_count = spacemit_get_functions_count,
.get_pin_muxing = spacemit_get_pin_muxing,
- .set_state = pinctrl_generic_set_state,
+ .set_state = spacemit_pinctrl_set_state,
.gpio_request_enable = spacemit_pinctrl_request_gpio,
.gpio_disable_free = spacemit_pinctrl_free_gpio,
.pinmux_set = spacemit_pinmux_set,
--
2.55.0
next prev parent reply other threads:[~2026-09-23 13:07 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-23 13:06 [PATCH v2 0/2] riscv: spacemit: add pinctrl support for K3 SoC Yixun Lan
2026-09-23 13:06 ` Yixun Lan [this message]
2026-09-23 13:06 ` [PATCH v2 2/2] pinctrl: spacemit: k3: add K3 pin support Yixun Lan
2026-10-07 9:12 ` E Shattow
2026-09-29 10:12 ` (subset) [PATCH v2 0/2] riscv: spacemit: add pinctrl support for K3 SoC Yixun Lan
2026-10-09 7:24 ` Yixun Lan
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=20260923-01-k3-pinctrl-support-v2-1-e76a917ee252@kernel.org \
--to=dlan@kernel.org \
--cc=eric.chung@riscstar.com \
--cc=junhui.liu@pigmoral.tech \
--cc=raymond.mao@riscstar.com \
--cc=trini@konsulko.com \
--cc=u-boot-spacemit@groups.io \
--cc=u-boot@lists.u-boot-project.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