linux-gpio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1 0/3] pinctrl: rockchip: Add RK3506 pinctrl support
@ 2025-11-04  2:12 Ye Zhang
  2025-11-04  2:12 ` [PATCH v1 1/3] dt-bindings: pinctrl: Add rk3506 " Ye Zhang
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Ye Zhang @ 2025-11-04  2:12 UTC (permalink / raw)
  To: Ye Zhang, Linus Walleij, Heiko Stuebner
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-gpio,
	devicetree, linux-arm-kernel, linux-rockchip, linux-kernel,
	tao.huang

This series adds pinctrl support for the Rockchip RK3506 SoC.

The series includes:
- RK3506 pinctrl driver implementation
- RMIO (Rockchip Matrix I/O) support for RK3506

Ye Zhang (3):
  dt-bindings: pinctrl: Add rk3506 pinctrl support
  pinctrl: rockchip: Add rk3506 pinctrl support
  pinctrl: rockchip: add rk3506 rmio support

 .../bindings/pinctrl/rockchip,pinctrl.yaml    |   1 +
 drivers/pinctrl/pinctrl-rockchip.c            | 517 +++++++++++++++++-
 drivers/pinctrl/pinctrl-rockchip.h            |   5 +
 3 files changed, 515 insertions(+), 8 deletions(-)

-- 
2.34.1


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

* [PATCH v1 1/3] dt-bindings: pinctrl: Add rk3506 pinctrl support
  2025-11-04  2:12 [PATCH v1 0/3] pinctrl: rockchip: Add RK3506 pinctrl support Ye Zhang
@ 2025-11-04  2:12 ` Ye Zhang
  2025-11-04 10:43   ` Heiko Stübner
  2025-11-04 14:06   ` Krzysztof Kozlowski
  2025-11-04  2:12 ` [PATCH v1 2/3] pinctrl: rockchip: " Ye Zhang
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 9+ messages in thread
From: Ye Zhang @ 2025-11-04  2:12 UTC (permalink / raw)
  To: Ye Zhang, Linus Walleij, Heiko Stuebner
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-gpio,
	devicetree, linux-arm-kernel, linux-rockchip, linux-kernel,
	tao.huang

Add the compatible string for the rk3506 SoC.

Signed-off-by: Ye Zhang <ye.zhang@rock-chips.com>
---
 Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml
index 125af766b992..76e607281716 100644
--- a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml
@@ -44,6 +44,7 @@ properties:
       - rockchip,rk3328-pinctrl
       - rockchip,rk3368-pinctrl
       - rockchip,rk3399-pinctrl
+      - rockchip,rk3506-pinctrl
       - rockchip,rk3528-pinctrl
       - rockchip,rk3562-pinctrl
       - rockchip,rk3568-pinctrl
-- 
2.34.1


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

* [PATCH v1 2/3] pinctrl: rockchip: Add rk3506 pinctrl support
  2025-11-04  2:12 [PATCH v1 0/3] pinctrl: rockchip: Add RK3506 pinctrl support Ye Zhang
  2025-11-04  2:12 ` [PATCH v1 1/3] dt-bindings: pinctrl: Add rk3506 " Ye Zhang
@ 2025-11-04  2:12 ` Ye Zhang
  2025-11-04 10:43   ` Heiko Stübner
  2025-11-04  2:12 ` [PATCH v1 3/3] pinctrl: rockchip: add rk3506 rmio support Ye Zhang
  2025-11-10 22:24 ` [PATCH v1 0/3] pinctrl: rockchip: Add RK3506 pinctrl support Linus Walleij
  3 siblings, 1 reply; 9+ messages in thread
From: Ye Zhang @ 2025-11-04  2:12 UTC (permalink / raw)
  To: Ye Zhang, Linus Walleij, Heiko Stuebner
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-gpio,
	devicetree, linux-arm-kernel, linux-rockchip, linux-kernel,
	tao.huang

Add support for the 5 rk3506 GPIO banks.

Signed-off-by: Ye Zhang <ye.zhang@rock-chips.com>
---
 drivers/pinctrl/pinctrl-rockchip.c | 442 ++++++++++++++++++++++++++++-
 drivers/pinctrl/pinctrl-rockchip.h |   4 +
 2 files changed, 438 insertions(+), 8 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 7a68a6237649..e44ef262beec 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -105,6 +105,29 @@
 		.pull_type[3] = pull3,					\
 	}
 
+#define PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS(id, pins, label, iom0,	\
+					       iom1, iom2, iom3,	\
+					       offset0, offset1,	\
+					       offset2, offset3, drv0,	\
+					       drv1, drv2, drv3)	\
+	{								\
+		.bank_num	= id,					\
+		.nr_pins	= pins,					\
+		.name		= label,				\
+		.iomux		= {					\
+			{ .type = iom0, .offset = offset0 },		\
+			{ .type = iom1, .offset = offset1 },		\
+			{ .type = iom2, .offset = offset2 },		\
+			{ .type = iom3, .offset = offset3 },		\
+		},							\
+		.drv		= {					\
+			{ .drv_type = drv0, .offset = -1 },		\
+			{ .drv_type = drv1, .offset = -1 },		\
+			{ .drv_type = drv2, .offset = -1 },		\
+			{ .drv_type = drv3, .offset = -1 },		\
+		},							\
+	}
+
 #define PIN_BANK_DRV_FLAGS(id, pins, label, type0, type1, type2, type3) \
 	{								\
 		.bank_num	= id,					\
@@ -233,6 +256,35 @@
 		.pull_type[3] = pull3,					\
 	}
 
+#define PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS_PULL_FLAGS(id, pins,	\
+						label, iom0, iom1,	\
+						iom2, iom3, offset0,	\
+						offset1, offset2,	\
+						offset3, drv0, drv1,	\
+						drv2, drv3, pull0,	\
+						pull1, pull2, pull3)	\
+	{								\
+		.bank_num	= id,					\
+		.nr_pins	= pins,					\
+		.name		= label,				\
+		.iomux		= {					\
+			{ .type = iom0, .offset = offset0 },		\
+			{ .type = iom1, .offset = offset1 },		\
+			{ .type = iom2, .offset = offset2 },		\
+			{ .type = iom3, .offset = offset3 },		\
+		},							\
+		.drv		= {					\
+			{ .drv_type = drv0, .offset = -1 },		\
+			{ .drv_type = drv1, .offset = -1 },		\
+			{ .drv_type = drv2, .offset = -1 },		\
+			{ .drv_type = drv3, .offset = -1 },		\
+		},							\
+		.pull_type[0] = pull0,					\
+		.pull_type[1] = pull1,					\
+		.pull_type[2] = pull2,					\
+		.pull_type[3] = pull3,					\
+	}
+
 #define PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, FLAG)		\
 	{								\
 		.bank_num	= ID,					\
@@ -1120,6 +1172,13 @@ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
 	else
 		regmap = info->regmap_base;
 
+	if (ctrl->type == RK3506) {
+		if (bank->bank_num == 1)
+			regmap = info->regmap_ioc1;
+		else if (bank->bank_num == 4)
+			return 0;
+	}
+
 	/* get basic quadrupel of mux registers and the correct reg inside */
 	mux_type = bank->iomux[iomux_num].type;
 	reg = bank->iomux[iomux_num].offset;
@@ -1239,6 +1298,13 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
 	else
 		regmap = info->regmap_base;
 
+	if (ctrl->type == RK3506) {
+		if (bank->bank_num == 1)
+			regmap = info->regmap_ioc1;
+		else if (bank->bank_num == 4)
+			return 0;
+	}
+
 	/* get basic quadrupel of mux registers and the correct reg inside */
 	mux_type = bank->iomux[iomux_num].type;
 	reg = bank->iomux[iomux_num].offset;
@@ -2003,6 +2069,262 @@ static int rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
 	return 0;
 }
 
+#define RK3506_DRV_BITS_PER_PIN		8
+#define RK3506_DRV_PINS_PER_REG		2
+#define RK3506_DRV_GPIO0_A_OFFSET	0x100
+#define RK3506_DRV_GPIO0_D_OFFSET	0x830
+#define RK3506_DRV_GPIO1_OFFSET		0x140
+#define RK3506_DRV_GPIO2_OFFSET		0x180
+#define RK3506_DRV_GPIO3_OFFSET		0x1c0
+#define RK3506_DRV_GPIO4_OFFSET		0x840
+
+static int rk3506_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+					int pin_num, struct regmap **regmap,
+					int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+	int ret = 0;
+
+	switch (bank->bank_num) {
+	case 0:
+		*regmap = info->regmap_pmu;
+		if (pin_num > 24) {
+			ret = -EINVAL;
+		} else if (pin_num < 24) {
+			*reg = RK3506_DRV_GPIO0_A_OFFSET;
+		} else {
+			*reg = RK3506_DRV_GPIO0_D_OFFSET;
+			*bit = 3;
+
+			return 0;
+		}
+		break;
+
+	case 1:
+		*regmap = info->regmap_ioc1;
+		if (pin_num < 28)
+			*reg = RK3506_DRV_GPIO1_OFFSET;
+		else
+			ret = -EINVAL;
+		break;
+
+	case 2:
+		*regmap = info->regmap_base;
+		if (pin_num < 17)
+			*reg = RK3506_DRV_GPIO2_OFFSET;
+		else
+			ret = -EINVAL;
+		break;
+
+	case 3:
+		*regmap = info->regmap_base;
+		if (pin_num < 15)
+			*reg = RK3506_DRV_GPIO3_OFFSET;
+		else
+			ret = -EINVAL;
+		break;
+
+	case 4:
+		*regmap = info->regmap_base;
+		if (pin_num < 8 || pin_num > 11) {
+			ret = -EINVAL;
+		} else {
+			*reg = RK3506_DRV_GPIO4_OFFSET;
+			*bit = 10;
+
+			return 0;
+		}
+		break;
+
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	if (ret) {
+		dev_err(info->dev, "unsupported bank_num %d pin_num %d\n", bank->bank_num, pin_num);
+
+		return ret;
+	}
+
+	*reg += ((pin_num / RK3506_DRV_PINS_PER_REG) * 4);
+	*bit = pin_num % RK3506_DRV_PINS_PER_REG;
+	*bit *= RK3506_DRV_BITS_PER_PIN;
+
+	return 0;
+}
+
+#define RK3506_PULL_BITS_PER_PIN	2
+#define RK3506_PULL_PINS_PER_REG	8
+#define RK3506_PULL_GPIO0_A_OFFSET	0x200
+#define RK3506_PULL_GPIO0_D_OFFSET	0x830
+#define RK3506_PULL_GPIO1_OFFSET	0x210
+#define RK3506_PULL_GPIO2_OFFSET	0x220
+#define RK3506_PULL_GPIO3_OFFSET	0x230
+#define RK3506_PULL_GPIO4_OFFSET	0x840
+
+static int rk3506_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+					 int pin_num, struct regmap **regmap,
+					 int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+	int ret = 0;
+
+	switch (bank->bank_num) {
+	case 0:
+		*regmap = info->regmap_pmu;
+		if (pin_num > 24) {
+			ret = -EINVAL;
+		} else if (pin_num < 24) {
+			*reg = RK3506_PULL_GPIO0_A_OFFSET;
+		} else {
+			*reg = RK3506_PULL_GPIO0_D_OFFSET;
+			*bit = 5;
+
+			return 0;
+		}
+		break;
+
+	case 1:
+		*regmap = info->regmap_ioc1;
+		if (pin_num < 28)
+			*reg = RK3506_PULL_GPIO1_OFFSET;
+		else
+			ret = -EINVAL;
+		break;
+
+	case 2:
+		*regmap = info->regmap_base;
+		if (pin_num < 17)
+			*reg = RK3506_PULL_GPIO2_OFFSET;
+		else
+			ret = -EINVAL;
+		break;
+
+	case 3:
+		*regmap = info->regmap_base;
+		if (pin_num < 15)
+			*reg = RK3506_PULL_GPIO3_OFFSET;
+		else
+			ret = -EINVAL;
+		break;
+
+	case 4:
+		*regmap = info->regmap_base;
+		if (pin_num < 8 || pin_num > 11) {
+			ret = -EINVAL;
+		} else {
+			*reg = RK3506_PULL_GPIO4_OFFSET;
+			*bit = 13;
+
+			return 0;
+		}
+		break;
+
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	if (ret) {
+		dev_err(info->dev, "unsupported bank_num %d pin_num %d\n", bank->bank_num, pin_num);
+
+		return ret;
+	}
+
+	*reg += ((pin_num / RK3506_PULL_PINS_PER_REG) * 4);
+	*bit = pin_num % RK3506_PULL_PINS_PER_REG;
+	*bit *= RK3506_PULL_BITS_PER_PIN;
+
+	return 0;
+}
+
+#define RK3506_SMT_BITS_PER_PIN		1
+#define RK3506_SMT_PINS_PER_REG		8
+#define RK3506_SMT_GPIO0_A_OFFSET	0x400
+#define RK3506_SMT_GPIO0_D_OFFSET	0x830
+#define RK3506_SMT_GPIO1_OFFSET		0x410
+#define RK3506_SMT_GPIO2_OFFSET		0x420
+#define RK3506_SMT_GPIO3_OFFSET		0x430
+#define RK3506_SMT_GPIO4_OFFSET		0x840
+
+static int rk3506_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+					   int pin_num,
+					   struct regmap **regmap,
+					   int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+	int ret = 0;
+
+	switch (bank->bank_num) {
+	case 0:
+		*regmap = info->regmap_pmu;
+		if (pin_num > 24) {
+			ret = -EINVAL;
+		} else if (pin_num < 24) {
+			*reg = RK3506_SMT_GPIO0_A_OFFSET;
+		} else {
+			*reg = RK3506_SMT_GPIO0_D_OFFSET;
+			*bit = 9;
+
+			return 0;
+		}
+		break;
+
+	case 1:
+		*regmap = info->regmap_ioc1;
+		if (pin_num < 28)
+			*reg = RK3506_SMT_GPIO1_OFFSET;
+		else
+			ret = -EINVAL;
+		break;
+
+	case 2:
+		*regmap = info->regmap_base;
+		if (pin_num < 17)
+			*reg = RK3506_SMT_GPIO2_OFFSET;
+		else
+			ret = -EINVAL;
+		break;
+
+	case 3:
+		*regmap = info->regmap_base;
+		if (pin_num < 15)
+			*reg = RK3506_SMT_GPIO3_OFFSET;
+		else
+			ret = -EINVAL;
+		break;
+
+	case 4:
+		*regmap = info->regmap_base;
+		if (pin_num < 8 || pin_num > 11) {
+			ret = -EINVAL;
+		} else {
+			*reg = RK3506_SMT_GPIO4_OFFSET;
+			*bit = 8;
+
+			return 0;
+		}
+		break;
+
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	if (ret) {
+		dev_err(info->dev, "unsupported bank_num %d pin_num %d\n", bank->bank_num, pin_num);
+
+		return ret;
+	}
+
+	*reg += ((pin_num / RK3506_SMT_PINS_PER_REG) * 4);
+	*bit = pin_num % RK3506_SMT_PINS_PER_REG;
+	*bit *= RK3506_SMT_BITS_PER_PIN;
+
+	return 0;
+}
+
 #define RK3528_DRV_BITS_PER_PIN		8
 #define RK3528_DRV_PINS_PER_REG		2
 #define RK3528_DRV_GPIO0_OFFSET		0x100
@@ -2749,7 +3071,8 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
 		rmask_bits = RK3588_DRV_BITS_PER_PIN;
 		ret = strength;
 		goto config;
-	} else if (ctrl->type == RK3528 ||
+	} else if (ctrl->type == RK3506 ||
+		   ctrl->type == RK3528 ||
 		   ctrl->type == RK3562 ||
 		   ctrl->type == RK3568) {
 		rmask_bits = RK3568_DRV_BITS_PER_PIN;
@@ -2828,12 +3151,37 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
 	case DRV_TYPE_IO_1V8_ONLY:
 		rmask_bits = RK3288_DRV_BITS_PER_PIN;
 		break;
+	case DRV_TYPE_IO_LEVEL_2_BIT:
+		ret = regmap_read(regmap, reg, &data);
+		if (ret)
+			return ret;
+		data >>= bit;
+
+		return data & 0x3;
+	case DRV_TYPE_IO_LEVEL_8_BIT:
+		ret = regmap_read(regmap, reg, &data);
+		if (ret)
+			return ret;
+		data >>= bit;
+		data &= (1 << 8) - 1;
+
+		ret = hweight8(data);
+		if (ret > 0)
+			return ret - 1;
+		else
+			return -EINVAL;
 	default:
 		dev_err(dev, "unsupported pinctrl drive type: %d\n", drv_type);
 		return -EINVAL;
 	}
 
 config:
+	if (ctrl->type == RK3506) {
+		if ((bank->bank_num == 0 && pin_num == 24) || bank->bank_num == 4) {
+			rmask_bits = 2;
+			ret = strength;
+		}
+	}
 	/* enable the write to the equivalent lower bits */
 	data = ((1 << rmask_bits) - 1) << (bit + 16);
 	rmask = data | (data >> 16);
@@ -2957,6 +3305,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
 	case RK3328:
 	case RK3368:
 	case RK3399:
+	case RK3506:
 	case RK3528:
 	case RK3562:
 	case RK3568:
@@ -3077,6 +3426,10 @@ static int rockchip_get_schmitt(struct rockchip_pin_bank *bank, int pin_num)
 		break;
 	}
 
+	if (ctrl->type == RK3506)
+		if ((bank->bank_num == 0 && pin_num == 24) ||  bank->bank_num == 4)
+			return data & 0x3;
+
 	return data & 0x1;
 }
 
@@ -3112,6 +3465,14 @@ static int rockchip_set_schmitt(struct rockchip_pin_bank *bank,
 		break;
 	}
 
+	if (ctrl->type == RK3506) {
+		if ((bank->bank_num == 0 && pin_num == 24) || bank->bank_num == 4) {
+			data = 0x3 << (bit + 16);
+			rmask = data | (data >> 16);
+			data |= ((enable ? 0x3 : 0) << bit);
+		}
+	}
+
 	return regmap_update_bits(regmap, reg, rmask, data);
 }
 
@@ -3227,6 +3588,7 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
 	case RK3328:
 	case RK3368:
 	case RK3399:
+	case RK3506:
 	case RK3528:
 	case RK3562:
 	case RK3568:
@@ -3880,13 +4242,10 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
 	}
 
 	/* try to find the optional reference to the pmu syscon */
-	node = of_parse_phandle(np, "rockchip,pmu", 0);
-	if (node) {
-		info->regmap_pmu = syscon_node_to_regmap(node);
-		of_node_put(node);
-		if (IS_ERR(info->regmap_pmu))
-			return PTR_ERR(info->regmap_pmu);
-	}
+	info->regmap_pmu = syscon_regmap_lookup_by_phandle_optional(np, "rockchip,pmu");
+
+	/* try to find the optional reference to the ioc1 syscon */
+	info->regmap_ioc1 = syscon_regmap_lookup_by_phandle_optional(np, "rockchip,ioc1");
 
 	ret = rockchip_pinctrl_register(pdev, info);
 	if (ret)
@@ -4350,6 +4709,71 @@ static struct rockchip_pin_ctrl rk3399_pin_ctrl = {
 		.drv_calc_reg		= rk3399_calc_drv_reg_and_bit,
 };
 
+static struct rockchip_pin_bank rk3506_pin_banks[] = {
+	PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS_PULL_FLAGS(0, 32, "gpio0",
+				    IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
+				    IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
+				    IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
+				    IOMUX_WIDTH_2BIT | IOMUX_SOURCE_PMU,
+				    0x0, 0x8, 0x10, 0x830,
+				    DRV_TYPE_IO_LEVEL_8_BIT,
+				    DRV_TYPE_IO_LEVEL_8_BIT,
+				    DRV_TYPE_IO_LEVEL_8_BIT,
+				    DRV_TYPE_IO_LEVEL_2_BIT,
+				    0, 0, 0, 1),
+	PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS(1, 32, "gpio1",
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    0x20, 0x28, 0x30, 0x38,
+				    DRV_TYPE_IO_LEVEL_8_BIT,
+				    DRV_TYPE_IO_LEVEL_8_BIT,
+				    DRV_TYPE_IO_LEVEL_8_BIT,
+				    DRV_TYPE_IO_LEVEL_8_BIT),
+	PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS(2, 32, "gpio2",
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    0x40, 0x48, 0x50, 0x58,
+				    DRV_TYPE_IO_LEVEL_8_BIT,
+				    DRV_TYPE_IO_LEVEL_8_BIT,
+				    DRV_TYPE_IO_LEVEL_8_BIT,
+				    DRV_TYPE_IO_LEVEL_8_BIT),
+	PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS(3, 32, "gpio3",
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    0x60, 0x68, 0x70, 0x78,
+				    DRV_TYPE_IO_LEVEL_8_BIT,
+				    DRV_TYPE_IO_LEVEL_8_BIT,
+				    DRV_TYPE_IO_LEVEL_8_BIT,
+				    DRV_TYPE_IO_LEVEL_8_BIT),
+	PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS_PULL_FLAGS(4, 32, "gpio4",
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    IOMUX_WIDTH_4BIT,
+				    0x80, 0x88, 0x90, 0x98,
+				    DRV_TYPE_IO_LEVEL_2_BIT,
+				    DRV_TYPE_IO_LEVEL_2_BIT,
+				    DRV_TYPE_IO_LEVEL_2_BIT,
+				    DRV_TYPE_IO_LEVEL_2_BIT,
+				    1, 1, 1, 1),
+};
+
+static struct rockchip_pin_ctrl rk3506_pin_ctrl __maybe_unused = {
+	.pin_banks		= rk3506_pin_banks,
+	.nr_banks		= ARRAY_SIZE(rk3506_pin_banks),
+	.label			= "RK3506-GPIO",
+	.type			= RK3506,
+	.pull_calc_reg		= rk3506_calc_pull_reg_and_bit,
+	.drv_calc_reg		= rk3506_calc_drv_reg_and_bit,
+	.schmitt_calc_reg	= rk3506_calc_schmitt_reg_and_bit,
+};
+
 static struct rockchip_pin_bank rk3528_pin_banks[] = {
 	PIN_BANK_IOMUX_FLAGS_OFFSET(0, 32, "gpio0",
 				    IOMUX_WIDTH_4BIT,
@@ -4560,6 +4984,8 @@ static const struct of_device_id rockchip_pinctrl_dt_match[] = {
 		.data = &rk3368_pin_ctrl },
 	{ .compatible = "rockchip,rk3399-pinctrl",
 		.data = &rk3399_pin_ctrl },
+	{ .compatible = "rockchip,rk3506-pinctrl",
+		.data = &rk3506_pin_ctrl },
 	{ .compatible = "rockchip,rk3528-pinctrl",
 		.data = &rk3528_pin_ctrl },
 	{ .compatible = "rockchip,rk3562-pinctrl",
diff --git a/drivers/pinctrl/pinctrl-rockchip.h b/drivers/pinctrl/pinctrl-rockchip.h
index 35cd38079d1e..4f4aff42a80a 100644
--- a/drivers/pinctrl/pinctrl-rockchip.h
+++ b/drivers/pinctrl/pinctrl-rockchip.h
@@ -196,6 +196,7 @@ enum rockchip_pinctrl_type {
 	RK3328,
 	RK3368,
 	RK3399,
+	RK3506,
 	RK3528,
 	RK3562,
 	RK3568,
@@ -260,6 +261,8 @@ enum rockchip_pin_drv_type {
 	DRV_TYPE_IO_1V8_ONLY,
 	DRV_TYPE_IO_1V8_3V0_AUTO,
 	DRV_TYPE_IO_3V3_ONLY,
+	DRV_TYPE_IO_LEVEL_2_BIT,
+	DRV_TYPE_IO_LEVEL_8_BIT,
 	DRV_TYPE_MAX
 };
 
@@ -458,6 +461,7 @@ struct rockchip_pinctrl {
 	int				reg_size;
 	struct regmap			*regmap_pull;
 	struct regmap			*regmap_pmu;
+	struct regmap			*regmap_ioc1;
 	struct device			*dev;
 	struct rockchip_pin_ctrl	*ctrl;
 	struct pinctrl_desc		pctl;
-- 
2.34.1


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

* [PATCH v1 3/3] pinctrl: rockchip: add rk3506 rmio support
  2025-11-04  2:12 [PATCH v1 0/3] pinctrl: rockchip: Add RK3506 pinctrl support Ye Zhang
  2025-11-04  2:12 ` [PATCH v1 1/3] dt-bindings: pinctrl: Add rk3506 " Ye Zhang
  2025-11-04  2:12 ` [PATCH v1 2/3] pinctrl: rockchip: " Ye Zhang
@ 2025-11-04  2:12 ` Ye Zhang
  2025-11-04 11:08   ` Heiko Stübner
  2025-11-10 22:24 ` [PATCH v1 0/3] pinctrl: rockchip: Add RK3506 pinctrl support Linus Walleij
  3 siblings, 1 reply; 9+ messages in thread
From: Ye Zhang @ 2025-11-04  2:12 UTC (permalink / raw)
  To: Ye Zhang, Linus Walleij, Heiko Stuebner
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-gpio,
	devicetree, linux-arm-kernel, linux-rockchip, linux-kernel,
	tao.huang

Support rockchip matrix io

Signed-off-by: Ye Zhang <ye.zhang@rock-chips.com>
---
 drivers/pinctrl/pinctrl-rockchip.c | 75 ++++++++++++++++++++++++++++++
 drivers/pinctrl/pinctrl-rockchip.h |  1 +
 2 files changed, 76 insertions(+)

diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index e44ef262beec..89ff8d8c7fcc 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -1258,6 +1258,74 @@ static int rockchip_verify_mux(struct rockchip_pin_bank *bank,
 	return 0;
 }
 
+static int rockchip_set_rmio(struct rockchip_pin_bank *bank, int pin, int *mux)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+	struct rockchip_pin_ctrl *ctrl = info->ctrl;
+	struct regmap *regmap;
+	int reg, function;
+	u32 data, rmask;
+	int ret = 0;
+	int iomux_num = (pin / 8);
+	u32 iomux_max, mux_type;
+
+	mux_type = bank->iomux[iomux_num].type;
+	if (mux_type & IOMUX_WIDTH_4BIT)
+		iomux_max = (1 << 4) - 1;
+	else if (mux_type & IOMUX_WIDTH_3BIT)
+		iomux_max = (1 << 3) - 1;
+	else
+		iomux_max = (1 << 2) - 1;
+
+	if (*mux > iomux_max)
+		function = *mux - iomux_max;
+	else
+		return 0;
+
+	switch (ctrl->type) {
+	case RK3506:
+		regmap = info->regmap_rmio;
+		if (bank->bank_num == 0) {
+			if (pin < 24)
+				reg = 0x80 + 0x4 * pin;
+			else
+				ret = -EINVAL;
+		} else if (bank->bank_num == 1) {
+			if (pin >= 9 && pin <= 11)
+				reg = 0xbc + 0x4 * pin;
+			else if (pin >= 18 && pin <= 19)
+				reg = 0xa4 + 0x4 * pin;
+			else if (pin >= 25 && pin <= 27)
+				reg = 0x90 + 0x4 * pin;
+			else
+				ret = -EINVAL;
+		} else {
+			ret = -EINVAL;
+		}
+
+		if (ret) {
+			dev_err(info->dev,
+				"rmio unsupported bank_num %d function %d\n",
+				bank->bank_num, function);
+
+			return -EINVAL;
+		}
+
+		rmask = 0x7f007f;
+		data = 0x7f0000 | function;
+		*mux = 7;
+		ret = regmap_update_bits(regmap, reg, rmask, data);
+		if (ret)
+			return ret;
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
 /*
  * Set a new mux function for a pin.
  *
@@ -1291,6 +1359,10 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
 
 	dev_dbg(dev, "setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
 
+	ret = rockchip_set_rmio(bank, pin, &mux);
+	if (ret)
+		return ret;
+
 	if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
 		regmap = info->regmap_pmu;
 	else if (bank->iomux[iomux_num].type & IOMUX_L_SOURCE_PMU)
@@ -4247,6 +4319,9 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
 	/* try to find the optional reference to the ioc1 syscon */
 	info->regmap_ioc1 = syscon_regmap_lookup_by_phandle_optional(np, "rockchip,ioc1");
 
+	/* try to find the optional reference to the rmio syscon */
+	info->regmap_rmio = syscon_regmap_lookup_by_phandle_optional(np, "rockchip,rmio");
+
 	ret = rockchip_pinctrl_register(pdev, info);
 	if (ret)
 		return ret;
diff --git a/drivers/pinctrl/pinctrl-rockchip.h b/drivers/pinctrl/pinctrl-rockchip.h
index 4f4aff42a80a..6d79ccf73b71 100644
--- a/drivers/pinctrl/pinctrl-rockchip.h
+++ b/drivers/pinctrl/pinctrl-rockchip.h
@@ -462,6 +462,7 @@ struct rockchip_pinctrl {
 	struct regmap			*regmap_pull;
 	struct regmap			*regmap_pmu;
 	struct regmap			*regmap_ioc1;
+	struct regmap			*regmap_rmio;
 	struct device			*dev;
 	struct rockchip_pin_ctrl	*ctrl;
 	struct pinctrl_desc		pctl;
-- 
2.34.1


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

* Re: [PATCH v1 1/3] dt-bindings: pinctrl: Add rk3506 pinctrl support
  2025-11-04  2:12 ` [PATCH v1 1/3] dt-bindings: pinctrl: Add rk3506 " Ye Zhang
@ 2025-11-04 10:43   ` Heiko Stübner
  2025-11-04 14:06   ` Krzysztof Kozlowski
  1 sibling, 0 replies; 9+ messages in thread
From: Heiko Stübner @ 2025-11-04 10:43 UTC (permalink / raw)
  To: Ye Zhang, Linus Walleij, Ye Zhang
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-gpio,
	devicetree, linux-arm-kernel, linux-rockchip, linux-kernel,
	tao.huang

Am Dienstag, 4. November 2025, 03:12:21 Mitteleuropäische Normalzeit schrieb Ye Zhang:
> Add the compatible string for the rk3506 SoC.
> 
> Signed-off-by: Ye Zhang <ye.zhang@rock-chips.com>

Reviewed-by: Heiko Stuebner <heiko@sntech.de>




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

* Re: [PATCH v1 2/3] pinctrl: rockchip: Add rk3506 pinctrl support
  2025-11-04  2:12 ` [PATCH v1 2/3] pinctrl: rockchip: " Ye Zhang
@ 2025-11-04 10:43   ` Heiko Stübner
  0 siblings, 0 replies; 9+ messages in thread
From: Heiko Stübner @ 2025-11-04 10:43 UTC (permalink / raw)
  To: Ye Zhang, Linus Walleij, Ye Zhang
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-gpio,
	devicetree, linux-arm-kernel, linux-rockchip, linux-kernel,
	tao.huang

Am Dienstag, 4. November 2025, 03:12:22 Mitteleuropäische Normalzeit schrieb Ye Zhang:
> Add support for the 5 rk3506 GPIO banks.
> 
> Signed-off-by: Ye Zhang <ye.zhang@rock-chips.com>

Reviewed-by: Heiko Stuebner <heiko@sntech.de>

> ---
>  drivers/pinctrl/pinctrl-rockchip.c | 442 ++++++++++++++++++++++++++++-
>  drivers/pinctrl/pinctrl-rockchip.h |   4 +
>  2 files changed, 438 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
> index 7a68a6237649..e44ef262beec 100644
> --- a/drivers/pinctrl/pinctrl-rockchip.c
> +++ b/drivers/pinctrl/pinctrl-rockchip.c
> @@ -105,6 +105,29 @@
>  		.pull_type[3] = pull3,					\
>  	}
>  
> +#define PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS(id, pins, label, iom0,	\
> +					       iom1, iom2, iom3,	\
> +					       offset0, offset1,	\
> +					       offset2, offset3, drv0,	\
> +					       drv1, drv2, drv3)	\
> +	{								\
> +		.bank_num	= id,					\
> +		.nr_pins	= pins,					\
> +		.name		= label,				\
> +		.iomux		= {					\
> +			{ .type = iom0, .offset = offset0 },		\
> +			{ .type = iom1, .offset = offset1 },		\
> +			{ .type = iom2, .offset = offset2 },		\
> +			{ .type = iom3, .offset = offset3 },		\
> +		},							\
> +		.drv		= {					\
> +			{ .drv_type = drv0, .offset = -1 },		\
> +			{ .drv_type = drv1, .offset = -1 },		\
> +			{ .drv_type = drv2, .offset = -1 },		\
> +			{ .drv_type = drv3, .offset = -1 },		\
> +		},							\
> +	}
> +
>  #define PIN_BANK_DRV_FLAGS(id, pins, label, type0, type1, type2, type3) \
>  	{								\
>  		.bank_num	= id,					\
> @@ -233,6 +256,35 @@
>  		.pull_type[3] = pull3,					\
>  	}
>  
> +#define PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS_PULL_FLAGS(id, pins,	\
> +						label, iom0, iom1,	\
> +						iom2, iom3, offset0,	\
> +						offset1, offset2,	\
> +						offset3, drv0, drv1,	\
> +						drv2, drv3, pull0,	\
> +						pull1, pull2, pull3)	\
> +	{								\
> +		.bank_num	= id,					\
> +		.nr_pins	= pins,					\
> +		.name		= label,				\
> +		.iomux		= {					\
> +			{ .type = iom0, .offset = offset0 },		\
> +			{ .type = iom1, .offset = offset1 },		\
> +			{ .type = iom2, .offset = offset2 },		\
> +			{ .type = iom3, .offset = offset3 },		\
> +		},							\
> +		.drv		= {					\
> +			{ .drv_type = drv0, .offset = -1 },		\
> +			{ .drv_type = drv1, .offset = -1 },		\
> +			{ .drv_type = drv2, .offset = -1 },		\
> +			{ .drv_type = drv3, .offset = -1 },		\
> +		},							\
> +		.pull_type[0] = pull0,					\
> +		.pull_type[1] = pull1,					\
> +		.pull_type[2] = pull2,					\
> +		.pull_type[3] = pull3,					\
> +	}
> +
>  #define PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, FLAG)		\
>  	{								\
>  		.bank_num	= ID,					\
> @@ -1120,6 +1172,13 @@ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
>  	else
>  		regmap = info->regmap_base;
>  
> +	if (ctrl->type == RK3506) {
> +		if (bank->bank_num == 1)
> +			regmap = info->regmap_ioc1;
> +		else if (bank->bank_num == 4)
> +			return 0;
> +	}
> +
>  	/* get basic quadrupel of mux registers and the correct reg inside */
>  	mux_type = bank->iomux[iomux_num].type;
>  	reg = bank->iomux[iomux_num].offset;
> @@ -1239,6 +1298,13 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
>  	else
>  		regmap = info->regmap_base;
>  
> +	if (ctrl->type == RK3506) {
> +		if (bank->bank_num == 1)
> +			regmap = info->regmap_ioc1;
> +		else if (bank->bank_num == 4)
> +			return 0;
> +	}
> +
>  	/* get basic quadrupel of mux registers and the correct reg inside */
>  	mux_type = bank->iomux[iomux_num].type;
>  	reg = bank->iomux[iomux_num].offset;
> @@ -2003,6 +2069,262 @@ static int rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
>  	return 0;
>  }
>  
> +#define RK3506_DRV_BITS_PER_PIN		8
> +#define RK3506_DRV_PINS_PER_REG		2
> +#define RK3506_DRV_GPIO0_A_OFFSET	0x100
> +#define RK3506_DRV_GPIO0_D_OFFSET	0x830
> +#define RK3506_DRV_GPIO1_OFFSET		0x140
> +#define RK3506_DRV_GPIO2_OFFSET		0x180
> +#define RK3506_DRV_GPIO3_OFFSET		0x1c0
> +#define RK3506_DRV_GPIO4_OFFSET		0x840
> +
> +static int rk3506_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
> +					int pin_num, struct regmap **regmap,
> +					int *reg, u8 *bit)
> +{
> +	struct rockchip_pinctrl *info = bank->drvdata;
> +	int ret = 0;
> +
> +	switch (bank->bank_num) {
> +	case 0:
> +		*regmap = info->regmap_pmu;
> +		if (pin_num > 24) {
> +			ret = -EINVAL;
> +		} else if (pin_num < 24) {
> +			*reg = RK3506_DRV_GPIO0_A_OFFSET;
> +		} else {
> +			*reg = RK3506_DRV_GPIO0_D_OFFSET;
> +			*bit = 3;
> +
> +			return 0;
> +		}
> +		break;
> +
> +	case 1:
> +		*regmap = info->regmap_ioc1;
> +		if (pin_num < 28)
> +			*reg = RK3506_DRV_GPIO1_OFFSET;
> +		else
> +			ret = -EINVAL;
> +		break;
> +
> +	case 2:
> +		*regmap = info->regmap_base;
> +		if (pin_num < 17)
> +			*reg = RK3506_DRV_GPIO2_OFFSET;
> +		else
> +			ret = -EINVAL;
> +		break;
> +
> +	case 3:
> +		*regmap = info->regmap_base;
> +		if (pin_num < 15)
> +			*reg = RK3506_DRV_GPIO3_OFFSET;
> +		else
> +			ret = -EINVAL;
> +		break;
> +
> +	case 4:
> +		*regmap = info->regmap_base;
> +		if (pin_num < 8 || pin_num > 11) {
> +			ret = -EINVAL;
> +		} else {
> +			*reg = RK3506_DRV_GPIO4_OFFSET;
> +			*bit = 10;
> +
> +			return 0;
> +		}
> +		break;
> +
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	if (ret) {
> +		dev_err(info->dev, "unsupported bank_num %d pin_num %d\n", bank->bank_num, pin_num);
> +
> +		return ret;
> +	}
> +
> +	*reg += ((pin_num / RK3506_DRV_PINS_PER_REG) * 4);
> +	*bit = pin_num % RK3506_DRV_PINS_PER_REG;
> +	*bit *= RK3506_DRV_BITS_PER_PIN;
> +
> +	return 0;
> +}
> +
> +#define RK3506_PULL_BITS_PER_PIN	2
> +#define RK3506_PULL_PINS_PER_REG	8
> +#define RK3506_PULL_GPIO0_A_OFFSET	0x200
> +#define RK3506_PULL_GPIO0_D_OFFSET	0x830
> +#define RK3506_PULL_GPIO1_OFFSET	0x210
> +#define RK3506_PULL_GPIO2_OFFSET	0x220
> +#define RK3506_PULL_GPIO3_OFFSET	0x230
> +#define RK3506_PULL_GPIO4_OFFSET	0x840
> +
> +static int rk3506_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
> +					 int pin_num, struct regmap **regmap,
> +					 int *reg, u8 *bit)
> +{
> +	struct rockchip_pinctrl *info = bank->drvdata;
> +	int ret = 0;
> +
> +	switch (bank->bank_num) {
> +	case 0:
> +		*regmap = info->regmap_pmu;
> +		if (pin_num > 24) {
> +			ret = -EINVAL;
> +		} else if (pin_num < 24) {
> +			*reg = RK3506_PULL_GPIO0_A_OFFSET;
> +		} else {
> +			*reg = RK3506_PULL_GPIO0_D_OFFSET;
> +			*bit = 5;
> +
> +			return 0;
> +		}
> +		break;
> +
> +	case 1:
> +		*regmap = info->regmap_ioc1;
> +		if (pin_num < 28)
> +			*reg = RK3506_PULL_GPIO1_OFFSET;
> +		else
> +			ret = -EINVAL;
> +		break;
> +
> +	case 2:
> +		*regmap = info->regmap_base;
> +		if (pin_num < 17)
> +			*reg = RK3506_PULL_GPIO2_OFFSET;
> +		else
> +			ret = -EINVAL;
> +		break;
> +
> +	case 3:
> +		*regmap = info->regmap_base;
> +		if (pin_num < 15)
> +			*reg = RK3506_PULL_GPIO3_OFFSET;
> +		else
> +			ret = -EINVAL;
> +		break;
> +
> +	case 4:
> +		*regmap = info->regmap_base;
> +		if (pin_num < 8 || pin_num > 11) {
> +			ret = -EINVAL;
> +		} else {
> +			*reg = RK3506_PULL_GPIO4_OFFSET;
> +			*bit = 13;
> +
> +			return 0;
> +		}
> +		break;
> +
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	if (ret) {
> +		dev_err(info->dev, "unsupported bank_num %d pin_num %d\n", bank->bank_num, pin_num);
> +
> +		return ret;
> +	}
> +
> +	*reg += ((pin_num / RK3506_PULL_PINS_PER_REG) * 4);
> +	*bit = pin_num % RK3506_PULL_PINS_PER_REG;
> +	*bit *= RK3506_PULL_BITS_PER_PIN;
> +
> +	return 0;
> +}
> +
> +#define RK3506_SMT_BITS_PER_PIN		1
> +#define RK3506_SMT_PINS_PER_REG		8
> +#define RK3506_SMT_GPIO0_A_OFFSET	0x400
> +#define RK3506_SMT_GPIO0_D_OFFSET	0x830
> +#define RK3506_SMT_GPIO1_OFFSET		0x410
> +#define RK3506_SMT_GPIO2_OFFSET		0x420
> +#define RK3506_SMT_GPIO3_OFFSET		0x430
> +#define RK3506_SMT_GPIO4_OFFSET		0x840
> +
> +static int rk3506_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
> +					   int pin_num,
> +					   struct regmap **regmap,
> +					   int *reg, u8 *bit)
> +{
> +	struct rockchip_pinctrl *info = bank->drvdata;
> +	int ret = 0;
> +
> +	switch (bank->bank_num) {
> +	case 0:
> +		*regmap = info->regmap_pmu;
> +		if (pin_num > 24) {
> +			ret = -EINVAL;
> +		} else if (pin_num < 24) {
> +			*reg = RK3506_SMT_GPIO0_A_OFFSET;
> +		} else {
> +			*reg = RK3506_SMT_GPIO0_D_OFFSET;
> +			*bit = 9;
> +
> +			return 0;
> +		}
> +		break;
> +
> +	case 1:
> +		*regmap = info->regmap_ioc1;
> +		if (pin_num < 28)
> +			*reg = RK3506_SMT_GPIO1_OFFSET;
> +		else
> +			ret = -EINVAL;
> +		break;
> +
> +	case 2:
> +		*regmap = info->regmap_base;
> +		if (pin_num < 17)
> +			*reg = RK3506_SMT_GPIO2_OFFSET;
> +		else
> +			ret = -EINVAL;
> +		break;
> +
> +	case 3:
> +		*regmap = info->regmap_base;
> +		if (pin_num < 15)
> +			*reg = RK3506_SMT_GPIO3_OFFSET;
> +		else
> +			ret = -EINVAL;
> +		break;
> +
> +	case 4:
> +		*regmap = info->regmap_base;
> +		if (pin_num < 8 || pin_num > 11) {
> +			ret = -EINVAL;
> +		} else {
> +			*reg = RK3506_SMT_GPIO4_OFFSET;
> +			*bit = 8;
> +
> +			return 0;
> +		}
> +		break;
> +
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	if (ret) {
> +		dev_err(info->dev, "unsupported bank_num %d pin_num %d\n", bank->bank_num, pin_num);
> +
> +		return ret;
> +	}
> +
> +	*reg += ((pin_num / RK3506_SMT_PINS_PER_REG) * 4);
> +	*bit = pin_num % RK3506_SMT_PINS_PER_REG;
> +	*bit *= RK3506_SMT_BITS_PER_PIN;
> +
> +	return 0;
> +}
> +
>  #define RK3528_DRV_BITS_PER_PIN		8
>  #define RK3528_DRV_PINS_PER_REG		2
>  #define RK3528_DRV_GPIO0_OFFSET		0x100
> @@ -2749,7 +3071,8 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
>  		rmask_bits = RK3588_DRV_BITS_PER_PIN;
>  		ret = strength;
>  		goto config;
> -	} else if (ctrl->type == RK3528 ||
> +	} else if (ctrl->type == RK3506 ||
> +		   ctrl->type == RK3528 ||
>  		   ctrl->type == RK3562 ||
>  		   ctrl->type == RK3568) {
>  		rmask_bits = RK3568_DRV_BITS_PER_PIN;
> @@ -2828,12 +3151,37 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
>  	case DRV_TYPE_IO_1V8_ONLY:
>  		rmask_bits = RK3288_DRV_BITS_PER_PIN;
>  		break;
> +	case DRV_TYPE_IO_LEVEL_2_BIT:
> +		ret = regmap_read(regmap, reg, &data);
> +		if (ret)
> +			return ret;
> +		data >>= bit;
> +
> +		return data & 0x3;
> +	case DRV_TYPE_IO_LEVEL_8_BIT:
> +		ret = regmap_read(regmap, reg, &data);
> +		if (ret)
> +			return ret;
> +		data >>= bit;
> +		data &= (1 << 8) - 1;
> +
> +		ret = hweight8(data);
> +		if (ret > 0)
> +			return ret - 1;
> +		else
> +			return -EINVAL;
>  	default:
>  		dev_err(dev, "unsupported pinctrl drive type: %d\n", drv_type);
>  		return -EINVAL;
>  	}
>  
>  config:
> +	if (ctrl->type == RK3506) {
> +		if ((bank->bank_num == 0 && pin_num == 24) || bank->bank_num == 4) {
> +			rmask_bits = 2;
> +			ret = strength;
> +		}
> +	}
>  	/* enable the write to the equivalent lower bits */
>  	data = ((1 << rmask_bits) - 1) << (bit + 16);
>  	rmask = data | (data >> 16);
> @@ -2957,6 +3305,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
>  	case RK3328:
>  	case RK3368:
>  	case RK3399:
> +	case RK3506:
>  	case RK3528:
>  	case RK3562:
>  	case RK3568:
> @@ -3077,6 +3426,10 @@ static int rockchip_get_schmitt(struct rockchip_pin_bank *bank, int pin_num)
>  		break;
>  	}
>  
> +	if (ctrl->type == RK3506)
> +		if ((bank->bank_num == 0 && pin_num == 24) ||  bank->bank_num == 4)
> +			return data & 0x3;
> +
>  	return data & 0x1;
>  }
>  
> @@ -3112,6 +3465,14 @@ static int rockchip_set_schmitt(struct rockchip_pin_bank *bank,
>  		break;
>  	}
>  
> +	if (ctrl->type == RK3506) {
> +		if ((bank->bank_num == 0 && pin_num == 24) || bank->bank_num == 4) {
> +			data = 0x3 << (bit + 16);
> +			rmask = data | (data >> 16);
> +			data |= ((enable ? 0x3 : 0) << bit);
> +		}
> +	}
> +
>  	return regmap_update_bits(regmap, reg, rmask, data);
>  }
>  
> @@ -3227,6 +3588,7 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
>  	case RK3328:
>  	case RK3368:
>  	case RK3399:
> +	case RK3506:
>  	case RK3528:
>  	case RK3562:
>  	case RK3568:
> @@ -3880,13 +4242,10 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
>  	}
>  
>  	/* try to find the optional reference to the pmu syscon */
> -	node = of_parse_phandle(np, "rockchip,pmu", 0);
> -	if (node) {
> -		info->regmap_pmu = syscon_node_to_regmap(node);
> -		of_node_put(node);
> -		if (IS_ERR(info->regmap_pmu))
> -			return PTR_ERR(info->regmap_pmu);
> -	}
> +	info->regmap_pmu = syscon_regmap_lookup_by_phandle_optional(np, "rockchip,pmu");
> +
> +	/* try to find the optional reference to the ioc1 syscon */
> +	info->regmap_ioc1 = syscon_regmap_lookup_by_phandle_optional(np, "rockchip,ioc1");
>  
>  	ret = rockchip_pinctrl_register(pdev, info);
>  	if (ret)
> @@ -4350,6 +4709,71 @@ static struct rockchip_pin_ctrl rk3399_pin_ctrl = {
>  		.drv_calc_reg		= rk3399_calc_drv_reg_and_bit,
>  };
>  
> +static struct rockchip_pin_bank rk3506_pin_banks[] = {
> +	PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS_PULL_FLAGS(0, 32, "gpio0",
> +				    IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
> +				    IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
> +				    IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
> +				    IOMUX_WIDTH_2BIT | IOMUX_SOURCE_PMU,
> +				    0x0, 0x8, 0x10, 0x830,
> +				    DRV_TYPE_IO_LEVEL_8_BIT,
> +				    DRV_TYPE_IO_LEVEL_8_BIT,
> +				    DRV_TYPE_IO_LEVEL_8_BIT,
> +				    DRV_TYPE_IO_LEVEL_2_BIT,
> +				    0, 0, 0, 1),
> +	PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS(1, 32, "gpio1",
> +				    IOMUX_WIDTH_4BIT,
> +				    IOMUX_WIDTH_4BIT,
> +				    IOMUX_WIDTH_4BIT,
> +				    IOMUX_WIDTH_4BIT,
> +				    0x20, 0x28, 0x30, 0x38,
> +				    DRV_TYPE_IO_LEVEL_8_BIT,
> +				    DRV_TYPE_IO_LEVEL_8_BIT,
> +				    DRV_TYPE_IO_LEVEL_8_BIT,
> +				    DRV_TYPE_IO_LEVEL_8_BIT),
> +	PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS(2, 32, "gpio2",
> +				    IOMUX_WIDTH_4BIT,
> +				    IOMUX_WIDTH_4BIT,
> +				    IOMUX_WIDTH_4BIT,
> +				    IOMUX_WIDTH_4BIT,
> +				    0x40, 0x48, 0x50, 0x58,
> +				    DRV_TYPE_IO_LEVEL_8_BIT,
> +				    DRV_TYPE_IO_LEVEL_8_BIT,
> +				    DRV_TYPE_IO_LEVEL_8_BIT,
> +				    DRV_TYPE_IO_LEVEL_8_BIT),
> +	PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS(3, 32, "gpio3",
> +				    IOMUX_WIDTH_4BIT,
> +				    IOMUX_WIDTH_4BIT,
> +				    IOMUX_WIDTH_4BIT,
> +				    IOMUX_WIDTH_4BIT,
> +				    0x60, 0x68, 0x70, 0x78,
> +				    DRV_TYPE_IO_LEVEL_8_BIT,
> +				    DRV_TYPE_IO_LEVEL_8_BIT,
> +				    DRV_TYPE_IO_LEVEL_8_BIT,
> +				    DRV_TYPE_IO_LEVEL_8_BIT),
> +	PIN_BANK_IOMUX_FLAGS_OFFSET_DRV_FLAGS_PULL_FLAGS(4, 32, "gpio4",
> +				    IOMUX_WIDTH_4BIT,
> +				    IOMUX_WIDTH_4BIT,
> +				    IOMUX_WIDTH_4BIT,
> +				    IOMUX_WIDTH_4BIT,
> +				    0x80, 0x88, 0x90, 0x98,
> +				    DRV_TYPE_IO_LEVEL_2_BIT,
> +				    DRV_TYPE_IO_LEVEL_2_BIT,
> +				    DRV_TYPE_IO_LEVEL_2_BIT,
> +				    DRV_TYPE_IO_LEVEL_2_BIT,
> +				    1, 1, 1, 1),
> +};
> +
> +static struct rockchip_pin_ctrl rk3506_pin_ctrl __maybe_unused = {
> +	.pin_banks		= rk3506_pin_banks,
> +	.nr_banks		= ARRAY_SIZE(rk3506_pin_banks),
> +	.label			= "RK3506-GPIO",
> +	.type			= RK3506,
> +	.pull_calc_reg		= rk3506_calc_pull_reg_and_bit,
> +	.drv_calc_reg		= rk3506_calc_drv_reg_and_bit,
> +	.schmitt_calc_reg	= rk3506_calc_schmitt_reg_and_bit,
> +};
> +
>  static struct rockchip_pin_bank rk3528_pin_banks[] = {
>  	PIN_BANK_IOMUX_FLAGS_OFFSET(0, 32, "gpio0",
>  				    IOMUX_WIDTH_4BIT,
> @@ -4560,6 +4984,8 @@ static const struct of_device_id rockchip_pinctrl_dt_match[] = {
>  		.data = &rk3368_pin_ctrl },
>  	{ .compatible = "rockchip,rk3399-pinctrl",
>  		.data = &rk3399_pin_ctrl },
> +	{ .compatible = "rockchip,rk3506-pinctrl",
> +		.data = &rk3506_pin_ctrl },
>  	{ .compatible = "rockchip,rk3528-pinctrl",
>  		.data = &rk3528_pin_ctrl },
>  	{ .compatible = "rockchip,rk3562-pinctrl",
> diff --git a/drivers/pinctrl/pinctrl-rockchip.h b/drivers/pinctrl/pinctrl-rockchip.h
> index 35cd38079d1e..4f4aff42a80a 100644
> --- a/drivers/pinctrl/pinctrl-rockchip.h
> +++ b/drivers/pinctrl/pinctrl-rockchip.h
> @@ -196,6 +196,7 @@ enum rockchip_pinctrl_type {
>  	RK3328,
>  	RK3368,
>  	RK3399,
> +	RK3506,
>  	RK3528,
>  	RK3562,
>  	RK3568,
> @@ -260,6 +261,8 @@ enum rockchip_pin_drv_type {
>  	DRV_TYPE_IO_1V8_ONLY,
>  	DRV_TYPE_IO_1V8_3V0_AUTO,
>  	DRV_TYPE_IO_3V3_ONLY,
> +	DRV_TYPE_IO_LEVEL_2_BIT,
> +	DRV_TYPE_IO_LEVEL_8_BIT,
>  	DRV_TYPE_MAX
>  };
>  
> @@ -458,6 +461,7 @@ struct rockchip_pinctrl {
>  	int				reg_size;
>  	struct regmap			*regmap_pull;
>  	struct regmap			*regmap_pmu;
> +	struct regmap			*regmap_ioc1;
>  	struct device			*dev;
>  	struct rockchip_pin_ctrl	*ctrl;
>  	struct pinctrl_desc		pctl;
> 





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

* Re: [PATCH v1 3/3] pinctrl: rockchip: add rk3506 rmio support
  2025-11-04  2:12 ` [PATCH v1 3/3] pinctrl: rockchip: add rk3506 rmio support Ye Zhang
@ 2025-11-04 11:08   ` Heiko Stübner
  0 siblings, 0 replies; 9+ messages in thread
From: Heiko Stübner @ 2025-11-04 11:08 UTC (permalink / raw)
  To: Ye Zhang, Linus Walleij, Ye Zhang
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-gpio,
	devicetree, linux-arm-kernel, linux-rockchip, linux-kernel,
	tao.huang

Am Dienstag, 4. November 2025, 03:12:23 Mitteleuropäische Normalzeit schrieb Ye Zhang:
> Support rockchip matrix io
> 
> Signed-off-by: Ye Zhang <ye.zhang@rock-chips.com>
> ---
>  drivers/pinctrl/pinctrl-rockchip.c | 75 ++++++++++++++++++++++++++++++
>  drivers/pinctrl/pinctrl-rockchip.h |  1 +
>  2 files changed, 76 insertions(+)

Here I disagree though.

The RMIO controller is a completely separate thing and from what I understand
from the documentation

- you set the pinmux to go to the rmio controller, and then that controller
  selects the function for this pin.

For example pinmux values for gpio0a7_sel are
- 0: GPIO0_A7
- 1: F SAI0_SDI3
- 2: SPI1_CSN1
- 7: RM_IO7

With 7 being the route to the matrix-io controller.


So lumping this into the main pinctrl feels definitly wrong, as then you
create a number of "virtual" pinmuxes where they don't belong.

So instead of trying to bolt this onto the main pinctrl, I'd like things
to be separate ... for the main iomux you route the pin to the rmio
controller and then have a separate configuration for the rmio marix.

bus2: bus2 {
	rockchip,pins = <0 RK_PA0 7 &pcfg_pull_none_drv_8ma>,
		<0 RK_PA1 7 &pcfg_pull_none_drv_8ma>,
		<0 RK_PA2 7 &pcfg_pull_none_drv_8ma>,
		<0 RK_PA3 7 &pcfg_pull_none_drv_8ma>,

	rockchip,rmio-pins {
		/* some way to sanely describe the rmio-config */
		pins = "GPIO0_A0", "GPIO0_A1";
		functions = "i2c0-scl", "i2c0-sda";
	};
};

This is especially true, as each pin in the rmio-controller can have each
function. So gpio0-a0 can be uart1-tx, uart1-rx etc etc ... 98 different
functions according to the documentation.


Heiko

> 
> diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
> index e44ef262beec..89ff8d8c7fcc 100644
> --- a/drivers/pinctrl/pinctrl-rockchip.c
> +++ b/drivers/pinctrl/pinctrl-rockchip.c
> @@ -1258,6 +1258,74 @@ static int rockchip_verify_mux(struct rockchip_pin_bank *bank,
>  	return 0;
>  }
>  
> +static int rockchip_set_rmio(struct rockchip_pin_bank *bank, int pin, int *mux)
> +{
> +	struct rockchip_pinctrl *info = bank->drvdata;
> +	struct rockchip_pin_ctrl *ctrl = info->ctrl;
> +	struct regmap *regmap;
> +	int reg, function;
> +	u32 data, rmask;
> +	int ret = 0;
> +	int iomux_num = (pin / 8);
> +	u32 iomux_max, mux_type;
> +
> +	mux_type = bank->iomux[iomux_num].type;
> +	if (mux_type & IOMUX_WIDTH_4BIT)
> +		iomux_max = (1 << 4) - 1;
> +	else if (mux_type & IOMUX_WIDTH_3BIT)
> +		iomux_max = (1 << 3) - 1;
> +	else
> +		iomux_max = (1 << 2) - 1;
> +
> +	if (*mux > iomux_max)
> +		function = *mux - iomux_max;
> +	else
> +		return 0;
> +
> +	switch (ctrl->type) {
> +	case RK3506:
> +		regmap = info->regmap_rmio;
> +		if (bank->bank_num == 0) {
> +			if (pin < 24)
> +				reg = 0x80 + 0x4 * pin;
> +			else
> +				ret = -EINVAL;
> +		} else if (bank->bank_num == 1) {
> +			if (pin >= 9 && pin <= 11)
> +				reg = 0xbc + 0x4 * pin;
> +			else if (pin >= 18 && pin <= 19)
> +				reg = 0xa4 + 0x4 * pin;
> +			else if (pin >= 25 && pin <= 27)
> +				reg = 0x90 + 0x4 * pin;
> +			else
> +				ret = -EINVAL;
> +		} else {
> +			ret = -EINVAL;
> +		}
> +
> +		if (ret) {
> +			dev_err(info->dev,
> +				"rmio unsupported bank_num %d function %d\n",
> +				bank->bank_num, function);
> +
> +			return -EINVAL;
> +		}
> +
> +		rmask = 0x7f007f;
> +		data = 0x7f0000 | function;
> +		*mux = 7;
> +		ret = regmap_update_bits(regmap, reg, rmask, data);
> +		if (ret)
> +			return ret;
> +		break;
> +
> +	default:
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
>  /*
>   * Set a new mux function for a pin.
>   *
> @@ -1291,6 +1359,10 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
>  
>  	dev_dbg(dev, "setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
>  
> +	ret = rockchip_set_rmio(bank, pin, &mux);
> +	if (ret)
> +		return ret;
> +
>  	if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
>  		regmap = info->regmap_pmu;
>  	else if (bank->iomux[iomux_num].type & IOMUX_L_SOURCE_PMU)
> @@ -4247,6 +4319,9 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
>  	/* try to find the optional reference to the ioc1 syscon */
>  	info->regmap_ioc1 = syscon_regmap_lookup_by_phandle_optional(np, "rockchip,ioc1");
>  
> +	/* try to find the optional reference to the rmio syscon */
> +	info->regmap_rmio = syscon_regmap_lookup_by_phandle_optional(np, "rockchip,rmio");
> +
>  	ret = rockchip_pinctrl_register(pdev, info);
>  	if (ret)
>  		return ret;
> diff --git a/drivers/pinctrl/pinctrl-rockchip.h b/drivers/pinctrl/pinctrl-rockchip.h
> index 4f4aff42a80a..6d79ccf73b71 100644
> --- a/drivers/pinctrl/pinctrl-rockchip.h
> +++ b/drivers/pinctrl/pinctrl-rockchip.h
> @@ -462,6 +462,7 @@ struct rockchip_pinctrl {
>  	struct regmap			*regmap_pull;
>  	struct regmap			*regmap_pmu;
>  	struct regmap			*regmap_ioc1;
> +	struct regmap			*regmap_rmio;
>  	struct device			*dev;
>  	struct rockchip_pin_ctrl	*ctrl;
>  	struct pinctrl_desc		pctl;
> 





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

* Re: [PATCH v1 1/3] dt-bindings: pinctrl: Add rk3506 pinctrl support
  2025-11-04  2:12 ` [PATCH v1 1/3] dt-bindings: pinctrl: Add rk3506 " Ye Zhang
  2025-11-04 10:43   ` Heiko Stübner
@ 2025-11-04 14:06   ` Krzysztof Kozlowski
  1 sibling, 0 replies; 9+ messages in thread
From: Krzysztof Kozlowski @ 2025-11-04 14:06 UTC (permalink / raw)
  To: Ye Zhang
  Cc: Linus Walleij, Heiko Stuebner, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-gpio, devicetree, linux-arm-kernel,
	linux-rockchip, linux-kernel, tao.huang

On Tue, Nov 04, 2025 at 10:12:21AM +0800, Ye Zhang wrote:
> Add the compatible string for the rk3506 SoC.
> 
> Signed-off-by: Ye Zhang <ye.zhang@rock-chips.com>
> ---
>  Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml | 1 +
>  1 file changed, 1 insertion(+)

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

Best regards,
Krzysztof


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

* Re: [PATCH v1 0/3] pinctrl: rockchip: Add RK3506 pinctrl support
  2025-11-04  2:12 [PATCH v1 0/3] pinctrl: rockchip: Add RK3506 pinctrl support Ye Zhang
                   ` (2 preceding siblings ...)
  2025-11-04  2:12 ` [PATCH v1 3/3] pinctrl: rockchip: add rk3506 rmio support Ye Zhang
@ 2025-11-10 22:24 ` Linus Walleij
  3 siblings, 0 replies; 9+ messages in thread
From: Linus Walleij @ 2025-11-10 22:24 UTC (permalink / raw)
  To: Ye Zhang
  Cc: Heiko Stuebner, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	linux-gpio, devicetree, linux-arm-kernel, linux-rockchip,
	linux-kernel, tao.huang

On Tue, Nov 4, 2025 at 3:12 AM Ye Zhang <ye.zhang@rock-chips.com> wrote:

> This series adds pinctrl support for the Rockchip RK3506 SoC.
>
> The series includes:
> - RK3506 pinctrl driver implementation
> - RMIO (Rockchip Matrix I/O) support for RK3506
>
> Ye Zhang (3):
>   dt-bindings: pinctrl: Add rk3506 pinctrl support
>   pinctrl: rockchip: Add rk3506 pinctrl support

Since we have consensus on these two patches I applied them!

>   pinctrl: rockchip: add rk3506 rmio support

Now you only need to discuss this with Heiko and iterate it.

Yours,
Linus Walleij

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

end of thread, other threads:[~2025-11-10 22:25 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-04  2:12 [PATCH v1 0/3] pinctrl: rockchip: Add RK3506 pinctrl support Ye Zhang
2025-11-04  2:12 ` [PATCH v1 1/3] dt-bindings: pinctrl: Add rk3506 " Ye Zhang
2025-11-04 10:43   ` Heiko Stübner
2025-11-04 14:06   ` Krzysztof Kozlowski
2025-11-04  2:12 ` [PATCH v1 2/3] pinctrl: rockchip: " Ye Zhang
2025-11-04 10:43   ` Heiko Stübner
2025-11-04  2:12 ` [PATCH v1 3/3] pinctrl: rockchip: add rk3506 rmio support Ye Zhang
2025-11-04 11:08   ` Heiko Stübner
2025-11-10 22:24 ` [PATCH v1 0/3] pinctrl: rockchip: Add RK3506 pinctrl support Linus Walleij

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).