* [PATCH v4 0/2] pinctrl: ultrarisc: add DP1000 pinctrl support
@ 2026-06-10 5:29 Jia Wang via B4 Relay
2026-06-10 5:29 ` [PATCH v4 1/2] dt-bindings: pinctrl: Add UltraRISC DP1000 pinctrl controller Jia Wang via B4 Relay
2026-06-10 5:29 ` [PATCH v4 2/2] pinctrl: ultrarisc: Add UltraRISC DP1000 pinctrl driver Jia Wang via B4 Relay
0 siblings, 2 replies; 5+ messages in thread
From: Jia Wang via B4 Relay @ 2026-06-10 5:29 UTC (permalink / raw)
To: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bartosz Golaszewski
Cc: linux-gpio, devicetree, linux-kernel, Jia Wang, Conor Dooley
This series adds the devicetree schema and the pinctrl driver for the
DP1000 controller using generic pinctrl bindings.
Compared with v1, this series is narrowed down to the pinctrl binding
and driver only. v1 patches 1, 2, 3, 5, 7, 8, and 9 (vendor prefix,
CPU/SoC bindings, DTS files, and defconfig update) are not included in
v2 and will be sent separately.
Note:
- ARCH_ULTRARISC support is being reviewed separately:
* Link: https://lore.kernel.org/lkml/20260427-ultrarisc-pcie-v4-1-98935f6cdfb5@ultrarisc.com/
Testing:
- dt_binding_check and yamllint
- Kernel build for RISC-V and boot-tested on DP1000 (Milk-V Titan and
Rongda M0)
Signed-off-by: Jia Wang <wangjia@ultrarisc.com>
---
Changes in v4:
- Drop the public DT binding header and document the numeric pin IDs
directly in the binding schema and examples.
- Drop the unnecessary GPIOLIB select from the pinctrl Kconfig.
- Replace the open-coded raw_spin_lock_irqsave()/unlock_irqrestore()
pairs with scoped guards.
- Add comments for ur_find_group_route().
- Remove the CONFIG_GENERIC_PINCONF ifdef around the generic pinconf
ops fields.
- Link to v3: https://patch.msgid.link/20260608-ultrarisc-pinctrl-v3-0-30a09ed74275@ultrarisc.com
Changes in v3:
- Re-add the DT binding header and use numeric pin IDs in the binding.
- Replace instance-specific mux names with generic function names.
- Tighten the schema constraints for A-D and LPC pins.
- Switch the driver to pinctrl_generic_pins_function_dt_node_to_map()
and resolve mux routes from the pins + function combination.
- Link to v2: https://patch.msgid.link/20260601-ultrarisc-pinctrl-v2-0-07ac5130a96d@ultrarisc.com
Changes in v2:
- Split the vendor prefix, CPU binding, SoC binding, DTS, and defconfig
patches out of this series for separate submission.
- Drop the legacy DT node format from both the binding and the driver,
and switch to the generic pinctrl interface with
pinconf_generic_dt_node_to_map_all().
- Drop the DT binding header from the series.
- Replace the generic func0/func1 mux names with named hardware functions
in the binding and driver.
- Wire the driver through CONFIG_PINCTRL_ULTRARISC and add COMPILE_TEST
coverage.
- Restrict function selection to valid pins in the driver.
- Link to v1: https://patch.msgid.link/20260515-ultrarisc-pinctrl-v1-0-bf559589ea8a@ultrarisc.com
---
Jia Wang (2):
dt-bindings: pinctrl: Add UltraRISC DP1000 pinctrl controller
pinctrl: ultrarisc: Add UltraRISC DP1000 pinctrl driver
.../bindings/pinctrl/ultrarisc,dp1000-pinctrl.yaml | 130 ++++++
MAINTAINERS | 7 +
drivers/pinctrl/Kconfig | 1 +
drivers/pinctrl/Makefile | 1 +
drivers/pinctrl/ultrarisc/Kconfig | 20 +
drivers/pinctrl/ultrarisc/Makefile | 4 +
drivers/pinctrl/ultrarisc/pinctrl-dp1000.c | 168 +++++++
drivers/pinctrl/ultrarisc/pinctrl-ultrarisc.c | 517 +++++++++++++++++++++
drivers/pinctrl/ultrarisc/pinctrl-ultrarisc.h | 63 +++
9 files changed, 911 insertions(+)
---
base-commit: 2d3090a8aeb596a26935db0955d46c9a5db5c6ce
change-id: 20260316-ultrarisc-pinctrl-efa6e24c4803
Best regards,
--
Jia Wang <wangjia@ultrarisc.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v4 1/2] dt-bindings: pinctrl: Add UltraRISC DP1000 pinctrl controller
2026-06-10 5:29 [PATCH v4 0/2] pinctrl: ultrarisc: add DP1000 pinctrl support Jia Wang via B4 Relay
@ 2026-06-10 5:29 ` Jia Wang via B4 Relay
2026-06-10 5:39 ` sashiko-bot
2026-06-10 5:29 ` [PATCH v4 2/2] pinctrl: ultrarisc: Add UltraRISC DP1000 pinctrl driver Jia Wang via B4 Relay
1 sibling, 1 reply; 5+ messages in thread
From: Jia Wang via B4 Relay @ 2026-06-10 5:29 UTC (permalink / raw)
To: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bartosz Golaszewski
Cc: linux-gpio, devicetree, linux-kernel, Jia Wang, Conor Dooley
From: Jia Wang <wangjia@ultrarisc.com>
Add doc for the pinctrl controllers on the UltraRISC DP1000 RISC-V SoC.
Signed-off-by: Jia Wang <wangjia@ultrarisc.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
---
.../bindings/pinctrl/ultrarisc,dp1000-pinctrl.yaml | 130 +++++++++++++++++++++
MAINTAINERS | 6 +
2 files changed, 136 insertions(+)
diff --git a/Documentation/devicetree/bindings/pinctrl/ultrarisc,dp1000-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/ultrarisc,dp1000-pinctrl.yaml
new file mode 100644
index 000000000000..c2332e6e60c2
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/ultrarisc,dp1000-pinctrl.yaml
@@ -0,0 +1,130 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/ultrarisc,dp1000-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: UltraRISC DP1000 Pin Controller
+
+maintainers:
+ - Jia Wang <wangjia@ultrarisc.com>
+
+description: |
+ UltraRISC RISC-V SoC DP1000 pin controller.
+ The controller manages ports A, B, C, D and LPC. Ports A-D default to
+ GPIO and provide additional SPI, UART, I2C, and PWM mux functions.
+ LPC pins default to the LPC interface and can be muxed to eSPI.
+ All pins also support pin configuration, including drive strength,
+ pull-up, and pull-down settings.
+
+properties:
+ compatible:
+ const: ultrarisc,dp1000-pinctrl
+
+ reg:
+ items:
+ - description: pin controller registers
+
+required:
+ - compatible
+ - reg
+
+patternProperties:
+ '.*-pins$':
+ type: object
+ unevaluatedProperties: false
+ allOf:
+ - $ref: /schemas/pinctrl/pincfg-node.yaml#
+ - $ref: /schemas/pinctrl/pinmux-node.yaml#
+ - if:
+ properties:
+ pins:
+ items:
+ minimum: 40
+ maximum: 52
+ then:
+ properties:
+ function:
+ enum:
+ - lpc
+ - espi
+ else:
+ properties:
+ pins:
+ items:
+ maximum: 39
+ function:
+ enum:
+ - gpio
+ - i2c
+ - pwm
+ - spi
+ - uart
+
+ properties:
+ pins:
+ description: |
+ List of pins affected by this state node, using numeric pin IDs.
+ Pins 0-39 correspond to ports A-D, and pins 40-52 correspond
+ to LPC0-LPC12.
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ minItems: 1
+ uniqueItems: true
+ items:
+ minimum: 0
+ maximum: 52
+
+ function:
+ description: |
+ Mux function to select for the listed pins. Supported functions
+ depend on the selected pins and match the DP1000 hardware mux
+ table.
+ enum:
+ - gpio
+ - i2c
+ - pwm
+ - spi
+ - uart
+ - lpc
+ - espi
+
+ bias-disable: true
+ bias-high-impedance: true
+ bias-pull-up: true
+ bias-pull-down: true
+
+ drive-strength:
+ description: Output drive strength in mA.
+ enum: [20, 27, 33, 40]
+
+ required:
+ - pins
+ - function
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ pinctrl@11081000 {
+ compatible = "ultrarisc,dp1000-pinctrl";
+ reg = <0x0 0x11081000 0x0 0x1000>;
+
+ i2c0-pins {
+ pins = <12 13>;
+ function = "i2c";
+ bias-pull-up;
+ drive-strength = <33>;
+ };
+
+ uart0-pins {
+ pins = <8 9>;
+ function = "uart";
+ bias-pull-up;
+ drive-strength = <33>;
+ };
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index e035a3be797c..1ef874d342a5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -27357,6 +27357,12 @@ S: Maintained
F: drivers/usb/common/ulpi.c
F: include/linux/ulpi/
+ULTRARISC DP1000 PINCTRL DRIVER
+M: Jia Wang <wangjia@ultrarisc.com>
+L: linux-gpio@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/pinctrl/ultrarisc,dp1000-pinctrl.yaml
+
ULTRATRONIK BOARD SUPPORT
M: Goran Rađenović <goran.radni@gmail.com>
M: Börge Strümpfel <boerge.struempfel@gmail.com>
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 2/2] pinctrl: ultrarisc: Add UltraRISC DP1000 pinctrl driver
2026-06-10 5:29 [PATCH v4 0/2] pinctrl: ultrarisc: add DP1000 pinctrl support Jia Wang via B4 Relay
2026-06-10 5:29 ` [PATCH v4 1/2] dt-bindings: pinctrl: Add UltraRISC DP1000 pinctrl controller Jia Wang via B4 Relay
@ 2026-06-10 5:29 ` Jia Wang via B4 Relay
2026-06-10 7:16 ` Bartosz Golaszewski
1 sibling, 1 reply; 5+ messages in thread
From: Jia Wang via B4 Relay @ 2026-06-10 5:29 UTC (permalink / raw)
To: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bartosz Golaszewski
Cc: linux-gpio, devicetree, linux-kernel, Jia Wang
From: Jia Wang <wangjia@ultrarisc.com>
Add support for the pin controller on the UltraRISC DP1000 SoC.
The controller provides mux selection for pins in ports A, B, C, D, and
LPC. Ports A-D default to GPIO and support peripheral muxing. LPC pins
can be switched to eSPI, but are not available as GPIOs. Basic pin
configuration controls such as drive strength, pull-up, and pull-down
are also supported.
Signed-off-by: Jia Wang <wangjia@ultrarisc.com>
---
MAINTAINERS | 1 +
drivers/pinctrl/Kconfig | 1 +
drivers/pinctrl/Makefile | 1 +
drivers/pinctrl/ultrarisc/Kconfig | 20 +
drivers/pinctrl/ultrarisc/Makefile | 4 +
drivers/pinctrl/ultrarisc/pinctrl-dp1000.c | 168 +++++++++
drivers/pinctrl/ultrarisc/pinctrl-ultrarisc.c | 517 ++++++++++++++++++++++++++
drivers/pinctrl/ultrarisc/pinctrl-ultrarisc.h | 63 ++++
8 files changed, 775 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 1ef874d342a5..04f2126d8af5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -27362,6 +27362,7 @@ M: Jia Wang <wangjia@ultrarisc.com>
L: linux-gpio@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pinctrl/ultrarisc,dp1000-pinctrl.yaml
+F: drivers/pinctrl/ultrarisc/*
ULTRATRONIK BOARD SUPPORT
M: Goran Rađenović <goran.radni@gmail.com>
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 03f2e3ee065f..2a5491e3fb47 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -708,6 +708,7 @@ source "drivers/pinctrl/sunplus/Kconfig"
source "drivers/pinctrl/sunxi/Kconfig"
source "drivers/pinctrl/tegra/Kconfig"
source "drivers/pinctrl/ti/Kconfig"
+source "drivers/pinctrl/ultrarisc/Kconfig"
source "drivers/pinctrl/uniphier/Kconfig"
source "drivers/pinctrl/visconti/Kconfig"
source "drivers/pinctrl/vt8500/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index f7d5d5f76d0c..61d502ba06b9 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -95,6 +95,7 @@ obj-y += sunplus/
obj-$(CONFIG_PINCTRL_SUNXI) += sunxi/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-y += ti/
+obj-$(CONFIG_PINCTRL_ULTRARISC) += ultrarisc/
obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
obj-$(CONFIG_PINCTRL_VISCONTI) += visconti/
obj-$(CONFIG_ARCH_VT8500) += vt8500/
diff --git a/drivers/pinctrl/ultrarisc/Kconfig b/drivers/pinctrl/ultrarisc/Kconfig
new file mode 100644
index 000000000000..80ac997f6c51
--- /dev/null
+++ b/drivers/pinctrl/ultrarisc/Kconfig
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config PINCTRL_ULTRARISC
+ tristate
+ depends on OF
+ depends on ARCH_ULTRARISC || COMPILE_TEST
+ select GENERIC_PINCTRL
+ select PINMUX
+
+config PINCTRL_ULTRARISC_DP1000
+ tristate "UltraRISC DP1000 SoC Pinctrl driver"
+ select PINCTRL_ULTRARISC
+ depends on OF && HAS_IOMEM
+ depends on ARCH_ULTRARISC || COMPILE_TEST
+ default ARCH_ULTRARISC
+ help
+ Say Y to select the pinctrl driver for UltraRISC DP1000 SoC.
+ This pin controller allows selecting the mux function for
+ each pin. This driver can also be built as a module called
+ pinctrl-dp1000.
diff --git a/drivers/pinctrl/ultrarisc/Makefile b/drivers/pinctrl/ultrarisc/Makefile
new file mode 100644
index 000000000000..5d49ce1c0af9
--- /dev/null
+++ b/drivers/pinctrl/ultrarisc/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_PINCTRL_ULTRARISC) += pinctrl-ultrarisc.o
+obj-$(CONFIG_PINCTRL_ULTRARISC_DP1000) += pinctrl-dp1000.o
diff --git a/drivers/pinctrl/ultrarisc/pinctrl-dp1000.c b/drivers/pinctrl/ultrarisc/pinctrl-dp1000.c
new file mode 100644
index 000000000000..f9c85c8c4433
--- /dev/null
+++ b/drivers/pinctrl/ultrarisc/pinctrl-dp1000.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2026 UltraRISC Technology (Shanghai) Co., Ltd.
+ *
+ * Author: Jia Wang <wangjia@ultrarisc.com>
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-ultrarisc.h"
+
+/* Port indices. */
+#define UR_DP1000_PORT_A_IDX 0
+#define UR_DP1000_PORT_B_IDX 1
+#define UR_DP1000_PORT_C_IDX 2
+#define UR_DP1000_PORT_D_IDX 3
+#define UR_DP1000_PORT_LPC_IDX 4
+
+/* Port mux register offsets. */
+#define UR_DP1000_PORTA_FUNC_OFFSET 0x2c0
+#define UR_DP1000_PORTB_FUNC_OFFSET 0x2c4
+#define UR_DP1000_PORTC_FUNC_OFFSET 0x2c8
+#define UR_DP1000_PORTD_FUNC_OFFSET 0x2cc
+#define UR_DP1000_PORTLPC_FUNC_OFFSET 0x2d0
+
+/* Port pinconf register offsets. */
+#define UR_DP1000_PORTA_CONF_OFFSET 0x310
+#define UR_DP1000_PORTB_CONF_OFFSET 0x318
+#define UR_DP1000_PORTC_CONF_OFFSET 0x31c
+#define UR_DP1000_PORTD_CONF_OFFSET 0x320
+#define UR_DP1000_PORTLPC_CONF_OFFSET 0x324
+
+/* Pin ranges for function descriptors. */
+#define UR_DP1000_PINS_ABCD GENMASK_ULL(39, 0)
+#define UR_DP1000_PINS_LPC GENMASK_ULL(52, 40)
+
+/* Static table entry helpers. */
+#define UR_DP1000_PORT(_base, _npins, _func, _conf, _modes, _gpio) \
+ { .pin_base = (_base), .npins = (_npins), .func_offset = (_func), \
+ .conf_offset = (_conf), .supported_modes = (_modes), \
+ .supports_gpio = (_gpio) }
+
+#define UR_DP1000_PIN(_nr, _name, _port) \
+ { .number = (_nr), .name = (_name), .drv_data = (void *)&ur_dp1000_ports[_port] }
+
+static const struct ur_func_route ur_dp1000_routes[] = {
+ { "gpio", UR_FUNC_DEFAULT, UR_DP1000_PINS_ABCD },
+ { "i2c", UR_FUNC_0, GENMASK_ULL(13, 12) },
+ { "i2c", UR_FUNC_0, GENMASK_ULL(23, 22) },
+ { "i2c", UR_FUNC_0, GENMASK_ULL(25, 24) },
+ { "i2c", UR_FUNC_0, GENMASK_ULL(27, 26) },
+ { "pwm", UR_FUNC_0, GENMASK_ULL(19, 16) },
+ { "spi", UR_FUNC_1, GENMASK_ULL(39, 32) },
+ { "spi", UR_FUNC_0, GENMASK_ULL(6, 0) },
+ { "uart", UR_FUNC_1, GENMASK_ULL(9, 8) },
+ { "uart", UR_FUNC_0, GENMASK_ULL(21, 20) },
+ { "uart", UR_FUNC_0, GENMASK_ULL(29, 28) },
+ { "uart", UR_FUNC_0, GENMASK_ULL(31, 30) },
+ { "lpc", UR_FUNC_DEFAULT, UR_DP1000_PINS_LPC },
+ { "espi", UR_FUNC_0, UR_DP1000_PINS_LPC },
+};
+
+static const struct ur_port_desc ur_dp1000_ports[] = {
+ UR_DP1000_PORT(0, 16, UR_DP1000_PORTA_FUNC_OFFSET,
+ UR_DP1000_PORTA_CONF_OFFSET,
+ UR_FUNC_0 | UR_FUNC_1, true),
+ UR_DP1000_PORT(16, 8, UR_DP1000_PORTB_FUNC_OFFSET,
+ UR_DP1000_PORTB_CONF_OFFSET,
+ UR_FUNC_0 | UR_FUNC_1, true),
+ UR_DP1000_PORT(24, 8, UR_DP1000_PORTC_FUNC_OFFSET,
+ UR_DP1000_PORTC_CONF_OFFSET,
+ UR_FUNC_0 | UR_FUNC_1, true),
+ UR_DP1000_PORT(32, 8, UR_DP1000_PORTD_FUNC_OFFSET,
+ UR_DP1000_PORTD_CONF_OFFSET,
+ UR_FUNC_0 | UR_FUNC_1, true),
+ UR_DP1000_PORT(40, 13, UR_DP1000_PORTLPC_FUNC_OFFSET,
+ UR_DP1000_PORTLPC_CONF_OFFSET,
+ UR_FUNC_0, false),
+};
+
+static const struct pinctrl_pin_desc ur_dp1000_pins[] = {
+ UR_DP1000_PIN(0, "PA0", UR_DP1000_PORT_A_IDX),
+ UR_DP1000_PIN(1, "PA1", UR_DP1000_PORT_A_IDX),
+ UR_DP1000_PIN(2, "PA2", UR_DP1000_PORT_A_IDX),
+ UR_DP1000_PIN(3, "PA3", UR_DP1000_PORT_A_IDX),
+ UR_DP1000_PIN(4, "PA4", UR_DP1000_PORT_A_IDX),
+ UR_DP1000_PIN(5, "PA5", UR_DP1000_PORT_A_IDX),
+ UR_DP1000_PIN(6, "PA6", UR_DP1000_PORT_A_IDX),
+ UR_DP1000_PIN(7, "PA7", UR_DP1000_PORT_A_IDX),
+ UR_DP1000_PIN(8, "PA8", UR_DP1000_PORT_A_IDX),
+ UR_DP1000_PIN(9, "PA9", UR_DP1000_PORT_A_IDX),
+ UR_DP1000_PIN(10, "PA10", UR_DP1000_PORT_A_IDX),
+ UR_DP1000_PIN(11, "PA11", UR_DP1000_PORT_A_IDX),
+ UR_DP1000_PIN(12, "PA12", UR_DP1000_PORT_A_IDX),
+ UR_DP1000_PIN(13, "PA13", UR_DP1000_PORT_A_IDX),
+ UR_DP1000_PIN(14, "PA14", UR_DP1000_PORT_A_IDX),
+ UR_DP1000_PIN(15, "PA15", UR_DP1000_PORT_A_IDX),
+ UR_DP1000_PIN(16, "PB0", UR_DP1000_PORT_B_IDX),
+ UR_DP1000_PIN(17, "PB1", UR_DP1000_PORT_B_IDX),
+ UR_DP1000_PIN(18, "PB2", UR_DP1000_PORT_B_IDX),
+ UR_DP1000_PIN(19, "PB3", UR_DP1000_PORT_B_IDX),
+ UR_DP1000_PIN(20, "PB4", UR_DP1000_PORT_B_IDX),
+ UR_DP1000_PIN(21, "PB5", UR_DP1000_PORT_B_IDX),
+ UR_DP1000_PIN(22, "PB6", UR_DP1000_PORT_B_IDX),
+ UR_DP1000_PIN(23, "PB7", UR_DP1000_PORT_B_IDX),
+ UR_DP1000_PIN(24, "PC0", UR_DP1000_PORT_C_IDX),
+ UR_DP1000_PIN(25, "PC1", UR_DP1000_PORT_C_IDX),
+ UR_DP1000_PIN(26, "PC2", UR_DP1000_PORT_C_IDX),
+ UR_DP1000_PIN(27, "PC3", UR_DP1000_PORT_C_IDX),
+ UR_DP1000_PIN(28, "PC4", UR_DP1000_PORT_C_IDX),
+ UR_DP1000_PIN(29, "PC5", UR_DP1000_PORT_C_IDX),
+ UR_DP1000_PIN(30, "PC6", UR_DP1000_PORT_C_IDX),
+ UR_DP1000_PIN(31, "PC7", UR_DP1000_PORT_C_IDX),
+ UR_DP1000_PIN(32, "PD0", UR_DP1000_PORT_D_IDX),
+ UR_DP1000_PIN(33, "PD1", UR_DP1000_PORT_D_IDX),
+ UR_DP1000_PIN(34, "PD2", UR_DP1000_PORT_D_IDX),
+ UR_DP1000_PIN(35, "PD3", UR_DP1000_PORT_D_IDX),
+ UR_DP1000_PIN(36, "PD4", UR_DP1000_PORT_D_IDX),
+ UR_DP1000_PIN(37, "PD5", UR_DP1000_PORT_D_IDX),
+ UR_DP1000_PIN(38, "PD6", UR_DP1000_PORT_D_IDX),
+ UR_DP1000_PIN(39, "PD7", UR_DP1000_PORT_D_IDX),
+ UR_DP1000_PIN(40, "LPC0", UR_DP1000_PORT_LPC_IDX),
+ UR_DP1000_PIN(41, "LPC1", UR_DP1000_PORT_LPC_IDX),
+ UR_DP1000_PIN(42, "LPC2", UR_DP1000_PORT_LPC_IDX),
+ UR_DP1000_PIN(43, "LPC3", UR_DP1000_PORT_LPC_IDX),
+ UR_DP1000_PIN(44, "LPC4", UR_DP1000_PORT_LPC_IDX),
+ UR_DP1000_PIN(45, "LPC5", UR_DP1000_PORT_LPC_IDX),
+ UR_DP1000_PIN(46, "LPC6", UR_DP1000_PORT_LPC_IDX),
+ UR_DP1000_PIN(47, "LPC7", UR_DP1000_PORT_LPC_IDX),
+ UR_DP1000_PIN(48, "LPC8", UR_DP1000_PORT_LPC_IDX),
+ UR_DP1000_PIN(49, "LPC9", UR_DP1000_PORT_LPC_IDX),
+ UR_DP1000_PIN(50, "LPC10", UR_DP1000_PORT_LPC_IDX),
+ UR_DP1000_PIN(51, "LPC11", UR_DP1000_PORT_LPC_IDX),
+ UR_DP1000_PIN(52, "LPC12", UR_DP1000_PORT_LPC_IDX),
+};
+
+static const struct ur_pinctrl_data ur_dp1000_pinctrl_data = {
+ .pins = ur_dp1000_pins,
+ .npins = ARRAY_SIZE(ur_dp1000_pins),
+ .routes = ur_dp1000_routes,
+ .num_routes = ARRAY_SIZE(ur_dp1000_routes),
+};
+
+static const struct of_device_id ur_pinctrl_of_match[] = {
+ { .compatible = "ultrarisc,dp1000-pinctrl" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ur_pinctrl_of_match);
+
+static int ur_dp1000_pinctrl_probe(struct platform_device *pdev)
+{
+ return ur_pinctrl_probe(pdev, &ur_dp1000_pinctrl_data);
+}
+
+static struct platform_driver ur_pinctrl_driver = {
+ .driver = {
+ .name = "ultrarisc-pinctrl-dp1000",
+ .of_match_table = ur_pinctrl_of_match,
+ },
+ .probe = ur_dp1000_pinctrl_probe,
+};
+
+module_platform_driver(ur_pinctrl_driver);
+
+MODULE_DESCRIPTION("UltraRISC DP1000 pinctrl driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/ultrarisc/pinctrl-ultrarisc.c b/drivers/pinctrl/ultrarisc/pinctrl-ultrarisc.c
new file mode 100644
index 000000000000..8fb5b0ea5b93
--- /dev/null
+++ b/drivers/pinctrl/ultrarisc/pinctrl-ultrarisc.c
@@ -0,0 +1,517 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2026 UltraRISC Technology (Shanghai) Co., Ltd.
+ *
+ * Author: Jia Wang <wangjia@ultrarisc.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+
+#include "../core.h"
+#include "../devicetree.h"
+#include "../pinconf.h"
+#include "../pinmux.h"
+
+#include "pinctrl-ultrarisc.h"
+
+#define UR_CONF_BIT_PER_PIN 4
+#define UR_CONF_PIN_PER_REG (32 / UR_CONF_BIT_PER_PIN)
+static const u32 ur_drive_strengths[] = { 20, 27, 33, 40 };
+
+static const struct ur_port_desc *ur_get_pin_port(struct pinctrl_dev *pctldev,
+ unsigned int pin)
+{
+ const struct pin_desc *desc = pin_desc_get(pctldev, pin);
+
+ if (!desc || !desc->drv_data)
+ return NULL;
+
+ return desc->drv_data;
+}
+
+static u32 ur_get_pin_conf_offset(const struct ur_port_desc *port_desc, u32 pin)
+{
+ return port_desc->conf_offset +
+ (pin / UR_CONF_PIN_PER_REG) * sizeof(u32);
+}
+
+static int ur_read_pin_conf(struct ur_pinctrl *pctrl, unsigned int pin, u32 *conf)
+{
+ const struct ur_port_desc *port_desc;
+ u32 pin_offset;
+ u32 reg_offset;
+ u32 shift;
+ u32 mask;
+
+ port_desc = ur_get_pin_port(pctrl->pctl_dev, pin);
+ if (!port_desc)
+ return -EINVAL;
+
+ pin_offset = pin - port_desc->pin_base;
+ reg_offset = ur_get_pin_conf_offset(port_desc, pin_offset);
+ shift = (pin_offset % UR_CONF_PIN_PER_REG) * UR_CONF_BIT_PER_PIN;
+ mask = GENMASK(UR_CONF_BIT_PER_PIN - 1, 0) << shift;
+ *conf = field_get(mask, readl_relaxed(pctrl->base + reg_offset));
+
+ return 0;
+}
+
+static int ur_write_pin_conf(struct ur_pinctrl *pctrl, unsigned int pin, u32 conf)
+{
+ const struct ur_port_desc *port_desc;
+ void __iomem *reg;
+ u32 pin_offset;
+ u32 reg_offset;
+ u32 shift;
+ u32 mask;
+ u32 val;
+
+ port_desc = ur_get_pin_port(pctrl->pctl_dev, pin);
+ if (!port_desc)
+ return -EINVAL;
+
+ pin_offset = pin - port_desc->pin_base;
+ reg_offset = ur_get_pin_conf_offset(port_desc, pin_offset);
+ reg = pctrl->base + reg_offset;
+ shift = (pin_offset % UR_CONF_PIN_PER_REG) * UR_CONF_BIT_PER_PIN;
+ mask = GENMASK(UR_CONF_BIT_PER_PIN - 1, 0) << shift;
+
+ scoped_guard(raw_spinlock_irqsave, &pctrl->lock) {
+ val = readl_relaxed(reg);
+ val = (val & ~mask) | field_prep(mask, conf);
+ writel_relaxed(val, reg);
+ }
+
+ return 0;
+}
+
+static int ur_set_pin_mux(struct ur_pinctrl *pctrl,
+ const struct ur_port_desc *port_desc,
+ u32 pin_offset, u32 mode)
+{
+ void __iomem *reg = pctrl->base + port_desc->func_offset;
+ u32 val;
+
+ if (WARN_ON(pin_offset >= UR_MAX_PINS_PER_PORT))
+ return -EINVAL;
+
+ scoped_guard(raw_spinlock_irqsave, &pctrl->lock) {
+ val = readl_relaxed(reg);
+ val &= ~((UR_FUNC_0 | UR_FUNC_1) << pin_offset);
+ val |= mode << pin_offset;
+ writel_relaxed(val, reg);
+ }
+
+ return 0;
+}
+
+static int ur_set_pin_mux_by_num(struct ur_pinctrl *pctrl, unsigned int pin, u32 mode)
+{
+ const struct ur_port_desc *port_desc = ur_get_pin_port(pctrl->pctl_dev, pin);
+ u32 pin_offset;
+
+ if (!port_desc)
+ return -EINVAL;
+
+ if (mode != UR_FUNC_DEFAULT && !(port_desc->supported_modes & mode))
+ return -EINVAL;
+
+ pin_offset = pin - port_desc->pin_base;
+
+ return ur_set_pin_mux(pctrl, port_desc, pin_offset, mode);
+}
+
+static int ur_hw_to_config(unsigned long *config, u32 conf)
+{
+ enum pin_config_param param = pinconf_to_config_param(*config);
+ u32 drive = FIELD_GET(UR_DRIVE_MASK, conf);
+ u32 pull = FIELD_GET(UR_PULL_MASK, conf);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
+ if (pull != UR_PULL_DIS)
+ return -EINVAL;
+ *config = pinconf_to_config_packed(param, 1);
+ return 0;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ if (pull != UR_PULL_UP)
+ return -EINVAL;
+ *config = pinconf_to_config_packed(param, 1);
+ return 0;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
+ if (pull != UR_PULL_DOWN)
+ return -EINVAL;
+ *config = pinconf_to_config_packed(param, 1);
+ return 0;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ if (drive >= ARRAY_SIZE(ur_drive_strengths))
+ return -EINVAL;
+ *config = pinconf_to_config_packed(param, ur_drive_strengths[drive]);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ur_config_to_hw(unsigned long config, u32 *conf)
+{
+ enum pin_config_param param = pinconf_to_config_param(config);
+ u32 arg = pinconf_to_config_argument(config);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
+ FIELD_MODIFY(UR_PULL_MASK, conf, UR_PULL_DIS);
+ return 0;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ FIELD_MODIFY(UR_PULL_MASK, conf, UR_PULL_UP);
+ return 0;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
+ FIELD_MODIFY(UR_PULL_MASK, conf, UR_PULL_DOWN);
+ return 0;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ for (u32 i = 0; i < ARRAY_SIZE(ur_drive_strengths); i++) {
+ if (ur_drive_strengths[i] != arg)
+ continue;
+ FIELD_MODIFY(UR_DRIVE_MASK, conf, i);
+ return 0;
+ }
+ return -EINVAL;
+ case PIN_CONFIG_PERSIST_STATE:
+ /*
+ * For PIN_CONFIG_PERSIST_STATE, gpiolib only treats
+ * -ENOTSUPP as an optional unsupported result.
+ * Do not use -EOPNOTSUPP here.
+ */
+ return -ENOTSUPP;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+/**
+ * ur_find_group_route() - Find the route matching a function and pin set
+ * @pctrl: pin controller instance
+ * @function: mux function name
+ * @group_mask: bitmap of pins in the selected group
+ * @route_out: returned route entry on success
+ *
+ * A mux function may be associated with multiple hardware routing options,
+ * each valid for a specific set of pins. This helper finds the unique route
+ * whose valid_pins mask covers all pins in @group_mask.
+ *
+ * The routing table must guarantee that a given function plus pin set
+ * resolves to exactly one route. If multiple routes match, the routing
+ * description is considered ambiguous and the lookup fails.
+ *
+ * Return: 0 on success, or -EINVAL if no matching route exists or if the
+ * routing table contains ambiguous entries.
+ */
+static int ur_find_group_route(struct ur_pinctrl *pctrl,
+ const char *function,
+ u64 group_mask,
+ const struct ur_func_route **route_out)
+{
+ const struct ur_func_route *match = NULL;
+
+ for (u32 i = 0; i < pctrl->data->num_routes; i++) {
+ const struct ur_func_route *route = &pctrl->data->routes[i];
+
+ if (strcmp(route->function, function))
+ continue;
+
+ if ((route->valid_pins & group_mask) != group_mask)
+ continue;
+
+ if (match) {
+ dev_err(pctrl->dev,
+ "ambiguous route for function %s group_mask=%#llx\n",
+ function, (unsigned long long)group_mask);
+ return -EINVAL;
+ }
+
+ match = route;
+ }
+
+ if (match) {
+ *route_out = match;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static const char *ur_get_group_function(struct pinctrl_dev *pctldev,
+ unsigned int group_selector,
+ unsigned int pin_index)
+{
+ const struct group_desc *group;
+ const char * const *functions;
+
+ group = pinctrl_generic_get_group(pctldev, group_selector);
+ if (!group || pin_index >= group->grp.npins || !group->data)
+ return NULL;
+
+ functions = group->data;
+
+ return functions[pin_index];
+}
+
+static int ur_resolve_group_mux(struct pinctrl_dev *pctldev,
+ struct ur_pinctrl *pctrl,
+ unsigned int group_selector,
+ const unsigned int *pins,
+ unsigned int npins,
+ const struct ur_func_route **route_out)
+{
+ const char *function;
+ u64 group_mask = 0;
+
+ if (!npins)
+ return -EINVAL;
+
+ function = ur_get_group_function(pctldev, group_selector, 0);
+ if (!function)
+ return -EINVAL;
+
+ for (u32 i = 0; i < npins; i++)
+ group_mask |= BIT_ULL(pins[i]);
+
+ return ur_find_group_route(pctrl, function, group_mask, route_out);
+}
+
+static bool ur_function_is_gpio(struct pinctrl_dev *pctldev,
+ unsigned int selector)
+{
+ const struct function_desc *function;
+
+ function = pinmux_generic_get_function(pctldev, selector);
+ if (!function)
+ return false;
+
+ for (u32 i = 0; i < function->func->ngroups; i++) {
+ const char *func_name;
+ int group_selector;
+
+ group_selector = pinctrl_get_group_selector(pctldev,
+ function->func->groups[i]);
+ if (group_selector < 0)
+ return false;
+
+ func_name = ur_get_group_function(pctldev, group_selector, 0);
+ if (!func_name || strcmp(func_name, "gpio"))
+ return false;
+ }
+
+ return true;
+}
+
+static const struct pinctrl_ops ur_pinctrl_ops = {
+ .get_groups_count = pinctrl_generic_get_group_count,
+ .get_group_name = pinctrl_generic_get_group_name,
+ .get_group_pins = pinctrl_generic_get_group_pins,
+ .dt_node_to_map = pinctrl_generic_pins_function_dt_node_to_map,
+ .dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static int ur_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset)
+{
+ struct ur_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ const struct ur_port_desc *port_desc;
+ const struct ur_func_route *route;
+ int ret;
+
+ (void)range;
+
+ port_desc = ur_get_pin_port(pctldev, offset);
+ if (!port_desc || !port_desc->supports_gpio)
+ return -EINVAL;
+
+ ret = ur_find_group_route(pctrl, "gpio", BIT_ULL(offset), &route);
+ if (ret)
+ return ret;
+
+ return ur_set_pin_mux_by_num(pctrl, offset, route->mode);
+}
+
+static int ur_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
+ unsigned int group_selector)
+{
+ struct ur_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ const struct ur_func_route *route;
+ const unsigned int *pins;
+ unsigned int npins;
+ int ret;
+
+ (void)func_selector;
+
+ ret = pinctrl_generic_get_group_pins(pctldev, group_selector, &pins, &npins);
+ if (ret)
+ return ret;
+
+ ret = ur_resolve_group_mux(pctldev, pctrl, group_selector, pins, npins,
+ &route);
+ if (ret)
+ return ret;
+
+ for (u32 i = 0; i < npins; i++) {
+ ret = ur_set_pin_mux_by_num(pctrl, pins[i], route->mode);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct pinmux_ops ur_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 = ur_function_is_gpio,
+ .set_mux = ur_set_mux,
+ .gpio_request_enable = ur_gpio_request_enable,
+ .strict = true,
+};
+
+static int ur_pin_config_get(struct pinctrl_dev *pctldev,
+ unsigned int pin,
+ unsigned long *config)
+{
+ struct ur_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ u32 conf;
+ int ret;
+
+ ret = ur_read_pin_conf(pctrl, pin, &conf);
+ if (ret)
+ return ret;
+
+ return ur_hw_to_config(config, conf);
+}
+
+static int ur_pin_config_set(struct pinctrl_dev *pctldev,
+ unsigned int pin,
+ unsigned long *configs,
+ unsigned int num_configs)
+{
+ struct ur_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+ u32 conf;
+ int ret;
+
+ ret = ur_read_pin_conf(pctrl, pin, &conf);
+ if (ret)
+ return ret;
+
+ for (u32 i = 0; i < num_configs; i++) {
+ ret = ur_config_to_hw(configs[i], &conf);
+ if (ret)
+ return ret;
+ }
+
+ return ur_write_pin_conf(pctrl, pin, conf);
+}
+
+static int ur_pin_config_group_get(struct pinctrl_dev *pctldev,
+ unsigned int selector,
+ unsigned long *config)
+{
+ const unsigned int *pins;
+ unsigned int npins;
+ int ret;
+
+ ret = pinctrl_generic_get_group_pins(pctldev, selector, &pins, &npins);
+ if (ret || !npins)
+ return ret ?: -EINVAL;
+
+ return ur_pin_config_get(pctldev, pins[0], config);
+}
+
+static int ur_pin_config_group_set(struct pinctrl_dev *pctldev,
+ unsigned int selector,
+ unsigned long *configs,
+ unsigned int num_configs)
+{
+ const unsigned int *pins;
+ unsigned int npins;
+ int ret;
+
+ ret = pinctrl_generic_get_group_pins(pctldev, selector, &pins, &npins);
+ if (ret)
+ return ret;
+
+ for (u32 i = 0; i < npins; i++) {
+ ret = ur_pin_config_set(pctldev, pins[i], configs, num_configs);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct pinconf_ops ur_pinconf_ops = {
+ .pin_config_get = ur_pin_config_get,
+ .pin_config_set = ur_pin_config_set,
+ .pin_config_group_get = ur_pin_config_group_get,
+ .pin_config_group_set = ur_pin_config_group_set,
+ .is_generic = true,
+ .pin_config_config_dbg_show = pinconf_generic_dump_config,
+};
+
+int ur_pinctrl_probe(struct platform_device *pdev,
+ const struct ur_pinctrl_data *data)
+{
+ struct pinctrl_desc *desc;
+ struct ur_pinctrl *pctrl;
+ int ret;
+
+ if (!data)
+ return -ENODEV;
+
+ desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
+ if (!pctrl)
+ return -ENOMEM;
+
+ pctrl->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(pctrl->base))
+ return PTR_ERR(pctrl->base);
+ pctrl->dev = &pdev->dev;
+ pctrl->data = data;
+
+ raw_spin_lock_init(&pctrl->lock);
+
+ desc->name = dev_name(&pdev->dev);
+ desc->owner = THIS_MODULE;
+ desc->pins = data->pins;
+ desc->npins = data->npins;
+ desc->pctlops = &ur_pinctrl_ops;
+ desc->pmxops = &ur_pinmux_ops;
+ desc->confops = &ur_pinconf_ops;
+
+ ret = devm_pinctrl_register_and_init(&pdev->dev, desc, pctrl, &pctrl->pctl_dev);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "failed to register pinctrl\n");
+
+ platform_set_drvdata(pdev, pctrl);
+
+ return pinctrl_enable(pctrl->pctl_dev);
+}
+EXPORT_SYMBOL_GPL(ur_pinctrl_probe);
+
+MODULE_DESCRIPTION("UltraRISC pinctrl core driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/ultrarisc/pinctrl-ultrarisc.h b/drivers/pinctrl/ultrarisc/pinctrl-ultrarisc.h
new file mode 100644
index 000000000000..c874688aafca
--- /dev/null
+++ b/drivers/pinctrl/ultrarisc/pinctrl-ultrarisc.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2026 UltraRISC Technology (Shanghai) Co., Ltd.
+ *
+ * Author: Jia Wang <wangjia@ultrarisc.com>
+ */
+
+#ifndef __PINCTRL_ULTRARISC_H__
+#define __PINCTRL_ULTRARISC_H__
+
+#include <linux/io.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/spinlock.h>
+
+struct platform_device;
+
+#define UR_FUNC_DEFAULT 0U
+#define UR_FUNC_0 1U
+#define UR_FUNC_1 0x10000U
+
+#define UR_MAX_PINS_PER_PORT 16
+
+#define UR_BIAS_MASK 0x0000000F
+#define UR_PULL_MASK 0x0C
+#define UR_PULL_DIS 0
+#define UR_PULL_UP 1
+#define UR_PULL_DOWN 2
+#define UR_DRIVE_MASK 0x03
+
+struct ur_port_desc {
+ u32 pin_base;
+ u32 npins;
+ u32 func_offset;
+ u32 conf_offset;
+ u32 supported_modes;
+ bool supports_gpio;
+};
+
+struct ur_func_route {
+ const char *function;
+ u32 mode;
+ u64 valid_pins;
+};
+
+struct ur_pinctrl_data {
+ const struct pinctrl_pin_desc *pins;
+ u32 npins;
+ const struct ur_func_route *routes;
+ u32 num_routes;
+};
+
+struct ur_pinctrl {
+ struct device *dev;
+ struct pinctrl_dev *pctl_dev;
+ const struct ur_pinctrl_data *data;
+ void __iomem *base;
+ raw_spinlock_t lock; /* Protects mux and conf registers */
+};
+
+int ur_pinctrl_probe(struct platform_device *pdev,
+ const struct ur_pinctrl_data *data);
+
+#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v4 1/2] dt-bindings: pinctrl: Add UltraRISC DP1000 pinctrl controller
2026-06-10 5:29 ` [PATCH v4 1/2] dt-bindings: pinctrl: Add UltraRISC DP1000 pinctrl controller Jia Wang via B4 Relay
@ 2026-06-10 5:39 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-06-10 5:39 UTC (permalink / raw)
To: Jia Wang via B4 Relay; +Cc: robh, conor+dt, devicetree
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] The use of `unevaluatedProperties: false` defeats the intended explicit restriction of standard pin configuration properties.
--
commit fcd21f9963cf534da789bb36bb2012a9e157e4d1
Author: Jia Wang <wangjia@ultrarisc.com>
dt-bindings: pinctrl: Add UltraRISC DP1000 pinctrl controller
This commit adds the device tree binding documentation for the pin controller
found on the UltraRISC DP1000 RISC-V SoC.
> diff --git a/Documentation/devicetree/bindings/pinctrl/ultrarisc,dp1000-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/ultrarisc,dp1000-pinctrl.yaml
> new file mode 100644
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/ultrarisc,dp1000-pinctrl.yaml
[ ... ]
> +patternProperties:
> + '.*-pins$':
> + type: object
> + unevaluatedProperties: false
> + allOf:
> + - $ref: /schemas/pinctrl/pincfg-node.yaml#
> + - $ref: /schemas/pinctrl/pinmux-node.yaml#
[Severity: Low]
Since this node uses unevaluatedProperties: false alongside a reference to
pincfg-node.yaml#, all standard pin configuration properties will be
inherently evaluated and allowed by the schema.
Does this defeat the intended explicit restriction of standard pin
configuration properties defined below?
[ ... ]
> + function:
> + description: |
> + Mux function to select for the listed pins. Supported functions
> + depend on the selected pins and match the DP1000 hardware mux
> + table.
> + enum:
> + - gpio
> + - i2c
> + - pwm
> + - spi
> + - uart
> + - lpc
> + - espi
> +
> + bias-disable: true
> + bias-high-impedance: true
> + bias-pull-up: true
> + bias-pull-down: true
> +
> + drive-strength:
> + description: Output drive strength in mA.
> + enum: [20, 27, 33, 40]
If the goal is to restrict the node to only these explicitly listed
properties, should additionalProperties: false be used in the
patternProperties block instead?
With unevaluatedProperties: false, unsupported properties like slew-rate or
input-debounce will silently pass schema validation, rendering these explicit
boolean property declarations redundant.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260610-ultrarisc-pinctrl-v4-0-b7e9b2a8ed84@ultrarisc.com?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v4 2/2] pinctrl: ultrarisc: Add UltraRISC DP1000 pinctrl driver
2026-06-10 5:29 ` [PATCH v4 2/2] pinctrl: ultrarisc: Add UltraRISC DP1000 pinctrl driver Jia Wang via B4 Relay
@ 2026-06-10 7:16 ` Bartosz Golaszewski
0 siblings, 0 replies; 5+ messages in thread
From: Bartosz Golaszewski @ 2026-06-10 7:16 UTC (permalink / raw)
To: wangjia
Cc: Jia Wang via B4 Relay, linux-gpio, devicetree, linux-kernel,
Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bartosz Golaszewski
On Wed, 10 Jun 2026 07:29:56 +0200, Jia Wang via B4 Relay
<devnull+wangjia.ultrarisc.com@kernel.org> said:
> From: Jia Wang <wangjia@ultrarisc.com>
>
> Add support for the pin controller on the UltraRISC DP1000 SoC.
>
> The controller provides mux selection for pins in ports A, B, C, D, and
> LPC. Ports A-D default to GPIO and support peripheral muxing. LPC pins
> can be switched to eSPI, but are not available as GPIOs. Basic pin
> configuration controls such as drive strength, pull-up, and pull-down
> are also supported.
>
> Signed-off-by: Jia Wang <wangjia@ultrarisc.com>
> ---
Looks pretty good to me.
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-06-10 7:16 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-10 5:29 [PATCH v4 0/2] pinctrl: ultrarisc: add DP1000 pinctrl support Jia Wang via B4 Relay
2026-06-10 5:29 ` [PATCH v4 1/2] dt-bindings: pinctrl: Add UltraRISC DP1000 pinctrl controller Jia Wang via B4 Relay
2026-06-10 5:39 ` sashiko-bot
2026-06-10 5:29 ` [PATCH v4 2/2] pinctrl: ultrarisc: Add UltraRISC DP1000 pinctrl driver Jia Wang via B4 Relay
2026-06-10 7:16 ` Bartosz Golaszewski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox