[PATCH v1 3/8] pinctrl: npcm8xx: support RG2 drive strength selection

Tomer Maimon <[email protected]> Wed, 15 Jul 2026 15:29:18 +0300
Newsgroups org.ozlabs.lists.openbmc,org.kernel.vger.linux-gpio,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
RG2 pins 110-113 and 208-209 do not use the per-bank ODSC bit that the
driver relies on for the rest of the drive-strength handling. Their
strength is encoded in GCR_DSCNT[7:6] and supports four values: 8, 12,
16 and 24mA.

Mark those pins as a dedicated drive-strength class and translate the
pinconf get/set operations to the shared GCR_DSCNT field so the full
hardware range becomes available.

Signed-off-by: Tomer Maimon <[email protected]>
---
 drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c | 75 ++++++++++++++++++++---
 1 file changed, 67 insertions(+), 8 deletions(-)

diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
index 1d5b3c648..8d7dfb326 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
@@ -82,6 +82,8 @@
 #define NPCM8XX_INTCR4_R1_RMII_EN	BIT(12)
 #define NPCM8XX_INTCR4_R2_RMII_EN	BIT(13)
 #define NPCM8XX_INTCR4_RMII3_EN	BIT(14)
+#define NPCM8XX_GCR_DSCNT_RG2DS_SHIFT	6
+#define NPCM8XX_GCR_DSCNT_RG2DS_MASK	GENMASK(7, 6)
 
 #define NPCM8XX_DEBOUNCE_MAX		4
 #define NPCM8XX_DEBOUNCE_NSEC		40
@@ -1287,6 +1289,7 @@ static struct pinfunction npcm8xx_funcs[] = {
 #define DRIVE_STRENGTH_LO_SHIFT		8
 #define DRIVE_STRENGTH_HI_SHIFT		12
 #define DRIVE_STRENGTH_MASK		GENMASK(15, 8)
+#define DSTR_RG2			BIT(16)
 
 #define DSTR(lo, hi)	(((lo) << DRIVE_STRENGTH_LO_SHIFT) | \
 			 ((hi) << DRIVE_STRENGTH_HI_SHIFT))
@@ -1419,10 +1422,10 @@ static const struct npcm8xx_pincfg pincfg[] = {
 	NPCM8XX_PINCFG(107,	i3c5, MFSEL3, 22,	none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		SLEW),
 	NPCM8XX_PINCFG(108,	sg1mdio, MFSEL4, 21,	none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		SLEW),
 	NPCM8XX_PINCFG(109,	sg1mdio, MFSEL4, 21,	none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		SLEW),
-	NPCM8XX_PINCFG(110,	rg2, MFSEL4, 24,	ddr, MFSEL3, 26,	rmii3, MFSEL5, 11,	none, NONE, 0,		none, NONE, 0,		SLEW),
-	NPCM8XX_PINCFG(111,	rg2, MFSEL4, 24,	ddr, MFSEL3, 26,	rmii3, MFSEL5, 11,	none, NONE, 0,		none, NONE, 0,		SLEW),
-	NPCM8XX_PINCFG(112,	rg2, MFSEL4, 24,	ddr, MFSEL3, 26,	none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		SLEW),
-	NPCM8XX_PINCFG(113,	rg2, MFSEL4, 24,	ddr, MFSEL3, 26,	none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		SLEW),
+	NPCM8XX_PINCFG(110,	rg2, MFSEL4, 24,	ddr, MFSEL3, 26,	rmii3, MFSEL5, 11,	none, NONE, 0,		none, NONE, 0,		DSTR_RG2 | SLEW),
+	NPCM8XX_PINCFG(111,	rg2, MFSEL4, 24,	ddr, MFSEL3, 26,	rmii3, MFSEL5, 11,	none, NONE, 0,		none, NONE, 0,		DSTR_RG2 | SLEW),
+	NPCM8XX_PINCFG(112,	rg2, MFSEL4, 24,	ddr, MFSEL3, 26,	none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		DSTR_RG2 | SLEW),
+	NPCM8XX_PINCFG(113,	rg2, MFSEL4, 24,	ddr, MFSEL3, 26,	none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		DSTR_RG2 | SLEW),
 	NPCM8XX_PINCFG(114,	smb0, MFSEL1, 6,	none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		0),
 	NPCM8XX_PINCFG(115,	smb0, MFSEL1, 6,	none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		0),
 	NPCM8XX_PINCFG(116,	smb1, MFSEL1, 7,	none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		0),
@@ -1513,8 +1516,8 @@ static const struct npcm8xx_pincfg pincfg[] = {
 	NPCM8XX_PINCFG(201,	r1, MFSEL3, 9,		none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		GPO),
 	NPCM8XX_PINCFG(202,	smb0c, I2CSEGSEL, 1,	fm0, MFSEL6, 16,	none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		SLEW),
 	NPCM8XX_PINCFG(203,	faninx, MFSEL3, 3,	spi1cs0, MFSEL3, 4,	fm1, MFSEL6, 17,	none, NONE, 0,		none, NONE, 0,		DSTR(8, 12)),
-	NPCM8XX_PINCFG(208,	rg2, MFSEL4, 24,	ddr, MFSEL3, 26,	none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		SLEW), /* DSCNT */
-	NPCM8XX_PINCFG(209,	rg2, MFSEL4, 24,	ddr, MFSEL3, 26,	rmii3, MFSEL5, 11,	none, NONE, 0,		none, NONE, 0,		SLEW), /* DSCNT */
+	NPCM8XX_PINCFG(208,	rg2, MFSEL4, 24,	ddr, MFSEL3, 26,	none, NONE, 0,		none, NONE, 0,		none, NONE, 0,		DSTR_RG2 | SLEW),
+	NPCM8XX_PINCFG(209,	rg2, MFSEL4, 24,	ddr, MFSEL3, 26,	rmii3, MFSEL5, 11,	none, NONE, 0,		none, NONE, 0,		DSTR_RG2 | SLEW),
 	NPCM8XX_PINCFG(210,	rg2, MFSEL4, 24,	ddr, MFSEL3, 26,	rmii3, MFSEL5, 11,	none, NONE, 0,		none, NONE, 0,		DSTR(8, 12) | SLEW),
 	NPCM8XX_PINCFG(211,	rg2, MFSEL4, 24,	ddr, MFSEL3, 26,	rmii3, MFSEL5, 11,	none, NONE, 0,		none, NONE, 0,		DSTR(8, 12) | SLEW),
 	NPCM8XX_PINCFG(212,	rg2, MFSEL4, 24,	ddr, MFSEL3, 26,	r3rxer, MFSEL6, 30,	none, NONE, 0,		none, NONE, 0,		DSTR(8, 12) | SLEW),
@@ -1954,6 +1957,56 @@ static int npcm8xx_set_slew_rate(struct npcm8xx_gpio *bank,
 	return 0;
 }
 
+static int npcm8xx_get_rg2_drive_strength(struct npcm8xx_pinctrl *npcm)
+{
+	u32 val;
+	int ret;
+
+	ret = regmap_read(npcm->gcr_regmap, NPCM8XX_GCR_DSCNT, &val);
+	if (ret)
+		return ret;
+
+	switch ((val & NPCM8XX_GCR_DSCNT_RG2DS_MASK) >>
+		NPCM8XX_GCR_DSCNT_RG2DS_SHIFT) {
+	case 0:
+		return 8;
+	case 1:
+		return 12;
+	case 2:
+		return 16;
+	case 3:
+		return 24;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int npcm8xx_set_rg2_drive_strength(struct npcm8xx_pinctrl *npcm, int nval)
+{
+	u32 val;
+
+	switch (nval) {
+	case 8:
+		val = 0;
+		break;
+	case 12:
+		val = 1;
+		break;
+	case 16:
+		val = 2;
+		break;
+	case 24:
+		val = 3;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return regmap_update_bits(npcm->gcr_regmap, NPCM8XX_GCR_DSCNT,
+				  NPCM8XX_GCR_DSCNT_RG2DS_MASK,
+				  val << NPCM8XX_GCR_DSCNT_RG2DS_SHIFT);
+}
+
 static int npcm8xx_get_drive_strength(struct pinctrl_dev *pctldev,
 				      unsigned int pin)
 {
@@ -1962,10 +2015,13 @@ static int npcm8xx_get_drive_strength(struct pinctrl_dev *pctldev,
 		&npcm->gpio_bank[pin / NPCM8XX_GPIO_PER_BANK];
 	int gpio = pin % bank->chip.gc.ngpio;
 	unsigned long pinmask = BIT(gpio);
-	int flg, val;
-	u32 ds = 0;
+	int flg, ds;
+	u32 val;
 
 	flg = pincfg[pin].flag;
+	if (flg & DSTR_RG2)
+		return npcm8xx_get_rg2_drive_strength(npcm);
+
 	if (!(flg & DRIVE_STRENGTH_MASK))
 		return -EINVAL;
 
@@ -1984,6 +2040,9 @@ static int npcm8xx_set_drive_strength(struct npcm8xx_pinctrl *npcm,
 	int gpio = BIT(pin % bank->chip.gc.ngpio);
 	int v;
 
+	if (pincfg[pin].flag & DSTR_RG2)
+		return npcm8xx_set_rg2_drive_strength(npcm, nval);
+
 	v = pincfg[pin].flag & DRIVE_STRENGTH_MASK;
 
 	if (DSLO(v) == nval)
-- 
2.34.1