pinctrl: npcm8xx: support RG2 drive strength selection

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 <tmaimon77@gmail.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
This commit is contained in:
Tomer Maimon
2026-07-15 15:29:18 +03:00
committed by Linus Walleij
parent c6ccdc3055
commit dc0e211e1a

View File

@@ -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)