Devicetree
 help / color / mirror / Atom feed
* [PATCH v2 0/2] pinctrl: ultrarisc: add DP1000 pinctrl support
@ 2026-06-01  9:56 Jia Wang via B4 Relay
  2026-06-01  9:56 ` [PATCH v2 1/2] dt-bindings: pinctrl: Add UltraRISC DP1000 pinctrl controller Jia Wang via B4 Relay
  2026-06-01  9:56 ` [PATCH v2 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-01  9:56 UTC (permalink / raw)
  To: Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Bartosz Golaszewski
  Cc: linux-gpio, devicetree, linux-kernel, Jia Wang

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 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 | 128 ++++++
 MAINTAINERS                                        |   7 +
 drivers/pinctrl/Kconfig                            |   1 +
 drivers/pinctrl/Makefile                           |   1 +
 drivers/pinctrl/ultrarisc/Kconfig                  |  23 +
 drivers/pinctrl/ultrarisc/Makefile                 |   4 +
 drivers/pinctrl/ultrarisc/pinctrl-dp1000.c         | 172 +++++++
 drivers/pinctrl/ultrarisc/pinctrl-ultrarisc.c      | 496 +++++++++++++++++++++
 drivers/pinctrl/ultrarisc/pinctrl-ultrarisc.h      |  75 ++++
 9 files changed, 907 insertions(+)
---
base-commit: 8fde5d1d47f69db6082dfa34500c27f8485389a5
change-id: 20260316-ultrarisc-pinctrl-efa6e24c4803

Best regards,
--  
Jia Wang <wangjia@ultrarisc.com>



^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 1/2] dt-bindings: pinctrl: Add UltraRISC DP1000 pinctrl controller
  2026-06-01  9:56 [PATCH v2 0/2] pinctrl: ultrarisc: add DP1000 pinctrl support Jia Wang via B4 Relay
@ 2026-06-01  9:56 ` Jia Wang via B4 Relay
  2026-06-01 10:06   ` sashiko-bot
  2026-06-01  9:56 ` [PATCH v2 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-01  9:56 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 doc for the pinctrl controllers on the UltraRISC DP1000 RISC-V SoC.

Signed-off-by: Jia Wang <wangjia@ultrarisc.com>
---
 .../bindings/pinctrl/ultrarisc,dp1000-pinctrl.yaml | 128 +++++++++++++++++++++
 MAINTAINERS                                        |   6 +
 2 files changed, 134 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..5100033c18c3
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/ultrarisc,dp1000-pinctrl.yaml
@@ -0,0 +1,128 @@
+# 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:
+              contains:
+                pattern: '^LPC([0-9]|1[0-2])$'
+        then:
+          properties:
+            function:
+              enum:
+                - lpc
+                - espi
+
+    properties:
+      pins:
+        description: List of pins affected by this state node.
+        minItems: 1
+        uniqueItems: true
+        items:
+          type: string
+          oneOf:
+            - pattern: '^PA([0-9]|1[0-5])$'
+            - pattern: '^PB[0-7]$'
+            - pattern: '^PC[0-7]$'
+            - pattern: '^PD[0-7]$'
+            - pattern: '^LPC([0-9]|1[0-2])$'
+
+      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
+          - i2c0
+          - i2c1
+          - i2c2
+          - i2c3
+          - pwm0
+          - pwm1
+          - pwm2
+          - pwm3
+          - spi0
+          - spi1
+          - uart0
+          - uart1
+          - uart2
+          - uart3
+          - 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 = "PA12", "PA13";
+          function = "i2c0";
+          bias-pull-up;
+          drive-strength = <33>;
+        };
+
+        uart0-pins {
+          pins = "PA8", "PA9";
+          function = "uart0";
+          bias-pull-up;
+          drive-strength = <33>;
+        };
+      };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 461a3eed6129..6fd7ce6365fb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -27356,6 +27356,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 v2 2/2] pinctrl: ultrarisc: Add UltraRISC DP1000 pinctrl driver
  2026-06-01  9:56 [PATCH v2 0/2] pinctrl: ultrarisc: add DP1000 pinctrl support Jia Wang via B4 Relay
  2026-06-01  9:56 ` [PATCH v2 1/2] dt-bindings: pinctrl: Add UltraRISC DP1000 pinctrl controller Jia Wang via B4 Relay
@ 2026-06-01  9:56 ` Jia Wang via B4 Relay
  2026-06-01 10:22   ` sashiko-bot
  1 sibling, 1 reply; 5+ messages in thread
From: Jia Wang via B4 Relay @ 2026-06-01  9:56 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             |  23 ++
 drivers/pinctrl/ultrarisc/Makefile            |   4 +
 drivers/pinctrl/ultrarisc/pinctrl-dp1000.c    | 172 +++++++++
 drivers/pinctrl/ultrarisc/pinctrl-ultrarisc.c | 496 ++++++++++++++++++++++++++
 drivers/pinctrl/ultrarisc/pinctrl-ultrarisc.h |  75 ++++
 8 files changed, 773 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 6fd7ce6365fb..bded23fc4474 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -27361,6 +27361,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..a9257dda5d65
--- /dev/null
+++ b/drivers/pinctrl/ultrarisc/Kconfig
@@ -0,0 +1,23 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config PINCTRL_ULTRARISC
+	tristate
+	depends on OF
+	depends on ARCH_ULTRARISC || COMPILE_TEST
+	select PINMUX
+	select GENERIC_PINCTRL_GROUPS
+	select GENERIC_PINCONF
+	select GENERIC_PINMUX_FUNCTIONS
+	select GPIOLIB
+
+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..c821f7b5d065
--- /dev/null
+++ b/drivers/pinctrl/ultrarisc/pinctrl-dp1000.c
@@ -0,0 +1,172 @@
+// 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_ALL	GENMASK_ULL(52, 0)
+#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_function_desc ur_dp1000_functions[] = {
+	{ "gpio", UR_FUNC_DEFAULT, true, UR_DP1000_PINS_ABCD },
+	{ "i2c0", UR_FUNC_0, false, GENMASK_ULL(13, 12) },
+	{ "i2c1", UR_FUNC_0, false, GENMASK_ULL(15, 14) | GENMASK_ULL(23, 22) },
+	{ "i2c2", UR_FUNC_0, false, GENMASK_ULL(25, 24) },
+	{ "i2c3", UR_FUNC_0, false, GENMASK_ULL(27, 26) },
+	{ "pwm0", UR_FUNC_0, false, BIT_ULL(16) },
+	{ "pwm1", UR_FUNC_0, false, BIT_ULL(17) },
+	{ "pwm2", UR_FUNC_0, false, BIT_ULL(18) },
+	{ "pwm3", UR_FUNC_0, false, BIT_ULL(19) },
+	{ "spi0", UR_FUNC_1, false, GENMASK_ULL(39, 32) },
+	{ "spi1", UR_FUNC_0, false, GENMASK_ULL(6, 0) },
+	{ "uart0", UR_FUNC_1, false, GENMASK_ULL(11, 4) },
+	{ "uart1", UR_FUNC_0, false, GENMASK_ULL(21, 20) },
+	{ "uart2", UR_FUNC_0, false, GENMASK_ULL(29, 28) },
+	{ "uart3", UR_FUNC_0, false, GENMASK_ULL(31, 30) },
+	{ "lpc", UR_FUNC_DEFAULT, false, UR_DP1000_PINS_LPC },
+	{ "espi", UR_FUNC_0, false, 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),
+	.functions = ur_dp1000_functions,
+	.num_functions = ARRAY_SIZE(ur_dp1000_functions),
+};
+
+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..99bd8a80fe43
--- /dev/null
+++ b/drivers/pinctrl/ultrarisc/pinctrl-ultrarisc.c
@@ -0,0 +1,496 @@
+// 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/of.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 "../pinctrl-utils.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 int 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 u32 ur_read_pin_conf(struct ur_pinctrl *pctrl, unsigned int pin)
+{
+	const struct ur_port_desc *port_desc;
+	struct ur_pin_val pin_val;
+	u32 reg_offset;
+	u32 shift;
+	u32 conf;
+	u32 mask;
+
+	port_desc = ur_get_pin_port(pctrl->pctl_dev, pin);
+	if (!port_desc)
+		return 0;
+
+	pin_val.port_desc = port_desc;
+	pin_val.pin = pin - port_desc->pin_base;
+	reg_offset = ur_get_pin_conf_offset(pin_val.port_desc, pin_val.pin);
+	shift = (pin_val.pin % 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 conf;
+}
+
+static int ur_write_pin_conf(struct ur_pinctrl *pctrl, unsigned int pin, u32 conf)
+{
+	const struct ur_port_desc *port_desc;
+	struct ur_pin_val pin_val;
+	unsigned long flags;
+	void __iomem *reg;
+	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_val.port_desc = port_desc;
+	pin_val.pin = pin - port_desc->pin_base;
+	reg_offset = ur_get_pin_conf_offset(pin_val.port_desc, pin_val.pin);
+	reg = pctrl->base + reg_offset;
+	shift = (pin_val.pin % UR_CONF_PIN_PER_REG) * UR_CONF_BIT_PER_PIN;
+	mask = GENMASK(UR_CONF_BIT_PER_PIN - 1, 0) << shift;
+
+	raw_spin_lock_irqsave(&pctrl->lock, flags);
+	val = readl_relaxed(reg);
+	val = (val & ~mask) | field_prep(mask, conf);
+	writel_relaxed(val, reg);
+	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+
+	return 0;
+}
+
+static int ur_set_pin_mux(struct ur_pinctrl *pctrl, struct ur_pin_val *pin_val)
+{
+	void __iomem *reg = pctrl->base + pin_val->port_desc->func_offset;
+	unsigned long flags;
+	u32 val;
+
+	if (WARN_ON(pin_val->pin >= UR_MAX_PINS_PER_PORT))
+		return -EINVAL;
+
+	raw_spin_lock_irqsave(&pctrl->lock, flags);
+	val = readl_relaxed(reg);
+	val &= ~((UR_FUNC_0 | UR_FUNC_1) << pin_val->pin);
+	val |= pin_val->mode << pin_val->pin;
+	writel_relaxed(val, reg);
+	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+
+	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);
+	struct ur_pin_val pin_val = { .mode = mode };
+
+	if (!port_desc)
+		return -EINVAL;
+
+	if (mode != UR_FUNC_DEFAULT && !(port_desc->supported_modes & mode))
+		return -EINVAL;
+
+	pin_val.port_desc = port_desc;
+	pin_val.pin = pin - port_desc->pin_base;
+
+	return ur_set_pin_mux(pctrl, &pin_val);
+}
+
+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;
+	}
+}
+
+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 = pinconf_generic_dt_node_to_map_all,
+	.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;
+
+	(void)range;
+
+	port_desc = ur_get_pin_port(pctldev, offset);
+	if (!port_desc || !port_desc->supports_gpio)
+		return -EINVAL;
+
+	return ur_set_pin_mux_by_num(pctrl, offset, UR_FUNC_DEFAULT);
+}
+
+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_function_desc *desc;
+	const struct function_desc *func;
+	const unsigned int *pins;
+	unsigned int npins;
+	int ret;
+
+	func = pinmux_generic_get_function(pctldev, func_selector);
+	if (!func || !func->data)
+		return -EINVAL;
+	desc = func->data;
+
+	ret = pinctrl_generic_get_group_pins(pctldev, group_selector, &pins, &npins);
+	if (ret)
+		return ret;
+
+	for (u32 i = 0; i < npins; i++) {
+		if (!(desc->valid_pins & BIT_ULL(pins[i])))
+			return -EINVAL;
+
+		ret = ur_set_pin_mux_by_num(pctrl, pins[i], desc->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 = pinmux_generic_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);
+
+	return ur_hw_to_config(config, ur_read_pin_conf(pctrl, pin));
+}
+
+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 = ur_read_pin_conf(pctrl, pin);
+	int 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,
+#ifdef CONFIG_GENERIC_PINCONF
+	.is_generic = true,
+	.pin_config_config_dbg_show = pinconf_generic_dump_config,
+#endif
+};
+
+static int ur_add_pin_groups(struct ur_pinctrl *pctrl)
+{
+	for (u32 i = 0; i < pctrl->data->npins; i++) {
+		int ret;
+
+		pctrl->group_names[i] = pctrl->data->pins[i].name;
+		pctrl->group_pins[i] = pctrl->data->pins[i].number;
+
+		ret = pinctrl_generic_add_group(pctrl->pctl_dev, pctrl->group_names[i],
+						&pctrl->group_pins[i], 1, NULL);
+		if (ret < 0)
+			return dev_err_probe(pctrl->dev, ret,
+					     "failed to add pin group %s\n",
+					     pctrl->group_names[i]);
+	}
+
+	return 0;
+}
+
+static int ur_collect_function_groups(struct ur_pinctrl *pctrl,
+				      const struct ur_function_desc *desc,
+				      const char ***groups,
+				      u32 *num_groups)
+{
+	const char **func_groups;
+	u32 count = 0;
+
+	for (u32 i = 0; i < pctrl->data->npins; i++) {
+		if (desc->valid_pins & BIT_ULL(pctrl->group_pins[i]))
+			count++;
+	}
+
+	if (!count) {
+		*groups = NULL;
+		*num_groups = 0;
+		return 0;
+	}
+
+	func_groups = devm_kcalloc(pctrl->dev, count, sizeof(*func_groups),
+				   GFP_KERNEL);
+	if (!func_groups)
+		return -ENOMEM;
+
+	*num_groups = 0;
+	for (u32 i = 0; i < pctrl->data->npins; i++) {
+		if (desc->valid_pins & BIT_ULL(pctrl->group_pins[i]))
+			func_groups[(*num_groups)++] = pctrl->group_names[i];
+	}
+
+	*groups = func_groups;
+
+	return 0;
+}
+
+static int ur_add_functions(struct ur_pinctrl *pctrl)
+{
+	for (u32 i = 0; i < pctrl->data->num_functions; i++) {
+		const struct ur_function_desc *desc = &pctrl->data->functions[i];
+		const char **func_groups;
+		struct pinfunction func;
+		u32 num_groups = 0;
+		int ret;
+
+		ret = ur_collect_function_groups(pctrl, desc, &func_groups,
+						 &num_groups);
+		if (ret)
+			return ret;
+
+		if (!num_groups)
+			continue;
+
+		func = desc->gpio ?
+			PINCTRL_GPIO_PINFUNCTION(desc->name, func_groups, num_groups) :
+			PINCTRL_PINFUNCTION(desc->name, func_groups, num_groups);
+
+		ret = pinmux_generic_add_pinfunction(pctrl->pctl_dev, &func, (void *)desc);
+		if (ret < 0)
+			return dev_err_probe(pctrl->dev, ret,
+					     "failed to add function %s\n",
+					     desc->name);
+	}
+
+	return 0;
+}
+
+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;
+	pctrl->group_names = devm_kcalloc(&pdev->dev, data->npins,
+					     sizeof(*pctrl->group_names), GFP_KERNEL);
+	if (!pctrl->group_names)
+		return -ENOMEM;
+
+	pctrl->group_pins = devm_kcalloc(&pdev->dev, data->npins,
+					    sizeof(*pctrl->group_pins), GFP_KERNEL);
+	if (!pctrl->group_pins)
+		return -ENOMEM;
+
+	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");
+
+	ret = ur_add_pin_groups(pctrl);
+	if (ret)
+		return ret;
+
+	ret = ur_add_functions(pctrl);
+	if (ret)
+		return ret;
+
+	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..9c2d31841af5
--- /dev/null
+++ b/drivers/pinctrl/ultrarisc/pinctrl-ultrarisc.h
@@ -0,0 +1,75 @@
+/* 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_function_desc {
+	const char *name;
+	u32 mode;
+	bool gpio;
+	u64 valid_pins;
+};
+
+struct ur_pin_val {
+	const struct ur_port_desc *port_desc;
+	u32 pin;
+	union {
+		u32 mode;
+		u32 conf;
+	};
+};
+
+struct ur_pinctrl_data {
+	const struct pinctrl_pin_desc *pins;
+	u32 npins;
+	const struct ur_function_desc *functions;
+	u32 num_functions;
+};
+
+struct ur_pinctrl {
+	struct device *dev;
+	struct pinctrl_dev *pctl_dev;
+	void __iomem *base;
+	const struct ur_pinctrl_data *data;
+	raw_spinlock_t lock;
+	const char **group_names;
+	unsigned int *group_pins;
+};
+
+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 v2 1/2] dt-bindings: pinctrl: Add UltraRISC DP1000 pinctrl controller
  2026-06-01  9:56 ` [PATCH v2 1/2] dt-bindings: pinctrl: Add UltraRISC DP1000 pinctrl controller Jia Wang via B4 Relay
@ 2026-06-01 10:06   ` sashiko-bot
  0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-06-01 10:06 UTC (permalink / raw)
  To: Jia Wang via B4 Relay; +Cc: devicetree, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] The conditional schema constraints fail to prevent non-LPC pins (Ports A-D) from being assigned the 'lpc' or 'espi' mux functions.
--

commit 579eeac83b351ad50317d72079e0436d73706e08
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. It defines properties for ports
A-D and LPC pins, including supported mux functions and pin configurations.

> 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#
> +      - if:
> +          properties:
> +            pins:
> +              contains:
> +                pattern: '^LPC([0-9]|1[0-2])$'
> +        then:
> +          properties:
> +            function:
> +              enum:
> +                - lpc
> +                - espi

[Severity: Low]
Does this schema allow Ports A-D to incorrectly select the lpc or espi
functions?

The if-then block restricts LPC pins to the lpc or espi functions, but it
appears to lack a reciprocal constraint preventing non-LPC pins from being
assigned to these functions.

Because lpc and espi are included in the base function enum defined later in
the schema, an invalid device tree might silently pass schema validation if it
mistakenly assigns the lpc or espi functions to Ports A-D.

Would it be helpful to add an else clause here, or a separate if-then block,
to explicitly forbid lpc and espi on non-LPC pins?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260601-ultrarisc-pinctrl-v2-0-07ac5130a96d@ultrarisc.com?part=1

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 2/2] pinctrl: ultrarisc: Add UltraRISC DP1000 pinctrl driver
  2026-06-01  9:56 ` [PATCH v2 2/2] pinctrl: ultrarisc: Add UltraRISC DP1000 pinctrl driver Jia Wang via B4 Relay
@ 2026-06-01 10:22   ` sashiko-bot
  0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-06-01 10:22 UTC (permalink / raw)
  To: Jia Wang via B4 Relay; +Cc: conor+dt, devicetree, robh

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The Kconfig symbol ARCH_ULTRARISC is referenced in 'depends on' and 'default' but is not defined anywhere in the kernel tree.
--

commit ae98cd11bdead29c422db358de808560e3f3ab23
Author: Jia Wang <wangjia@ultrarisc.com>

pinctrl: ultrarisc: Add UltraRISC DP1000 pinctrl driver

This commit adds support for the pin controller on the UltraRISC DP1000 SoC.
It provides mux selection for pins in ports A, B, C, D, and LPC, as well as
basic pin configuration controls.

[ ... ]

> diff --git a/drivers/pinctrl/ultrarisc/Kconfig b/drivers/pinctrl/ultrarisc/Kconfig
> new file mode 100644
> index 0000000000000..a9257dda5d656
> --- /dev/null
> +++ b/drivers/pinctrl/ultrarisc/Kconfig
> @@ -0,0 +1,23 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +
> +config PINCTRL_ULTRARISC
> +	tristate
> +	depends on OF
> +	depends on ARCH_ULTRARISC || COMPILE_TEST

[Severity: Medium]
Does ARCH_ULTRARISC exist in the kernel tree? I couldn't find a definition for
this Kconfig symbol. If it's missing, this driver will only be selectable
when COMPILE_TEST is enabled, leaving it disabled for its actual hardware
target.

> +	select PINMUX
> +	select GENERIC_PINCTRL_GROUPS
> +	select GENERIC_PINCONF
> +	select GENERIC_PINMUX_FUNCTIONS
> +	select GPIOLIB
> +
> +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

[Severity: Medium]
Similarly here, ARCH_ULTRARISC is used in the depends on and default directives
but appears to be undefined.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260601-ultrarisc-pinctrl-v2-0-07ac5130a96d@ultrarisc.com?part=2

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-06-01 10:22 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-01  9:56 [PATCH v2 0/2] pinctrl: ultrarisc: add DP1000 pinctrl support Jia Wang via B4 Relay
2026-06-01  9:56 ` [PATCH v2 1/2] dt-bindings: pinctrl: Add UltraRISC DP1000 pinctrl controller Jia Wang via B4 Relay
2026-06-01 10:06   ` sashiko-bot
2026-06-01  9:56 ` [PATCH v2 2/2] pinctrl: ultrarisc: Add UltraRISC DP1000 pinctrl driver Jia Wang via B4 Relay
2026-06-01 10:22   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox