Skip to content

Commit 586c4a3

Browse files
inochisasmb49
authored andcommitted
pinctrl: sophgo: avoid to modify untouched bit when setting cv1800 pinconf
BugLink: https://bugs.launchpad.net/bugs/2115678 [ Upstream commit ef1a5121ae3da02372fcb66d9632ed3d47ad5637 ] When setting pinconf configuration for cv1800 SoC, the driver just writes the value. It may zero some bits of the pinconf register and cause some unexpected error. Add a mask to avoid this. Signed-off-by: Inochi Amaoto <[email protected]> Link: https://lore.kernel.org/[email protected] Signed-off-by: Linus Walleij <[email protected]> Signed-off-by: Sasha Levin <[email protected]> Signed-off-by: Manuel Diewald <[email protected]> Signed-off-by: Mehmet Basaran <[email protected]>
1 parent 5f67a0b commit 586c4a3

File tree

1 file changed

+23
-10
lines changed

1 file changed

+23
-10
lines changed

drivers/pinctrl/sophgo/pinctrl-cv18xx.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -574,10 +574,10 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
574574
struct cv1800_pin *pin,
575575
unsigned long *configs,
576576
unsigned int num_configs,
577-
u32 *value)
577+
u32 *value, u32 *mask)
578578
{
579579
int i;
580-
u32 v = 0;
580+
u32 v = 0, m = 0;
581581
enum cv1800_pin_io_type type;
582582
int ret;
583583

@@ -596,61 +596,72 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
596596
case PIN_CONFIG_BIAS_PULL_DOWN:
597597
v &= ~PIN_IO_PULLDOWN;
598598
v |= FIELD_PREP(PIN_IO_PULLDOWN, arg);
599+
m |= PIN_IO_PULLDOWN;
599600
break;
600601
case PIN_CONFIG_BIAS_PULL_UP:
601602
v &= ~PIN_IO_PULLUP;
602603
v |= FIELD_PREP(PIN_IO_PULLUP, arg);
604+
m |= PIN_IO_PULLUP;
603605
break;
604606
case PIN_CONFIG_DRIVE_STRENGTH_UA:
605607
ret = cv1800_pinctrl_oc2reg(pctrl, pin, arg);
606608
if (ret < 0)
607609
return ret;
608610
v &= ~PIN_IO_DRIVE;
609611
v |= FIELD_PREP(PIN_IO_DRIVE, ret);
612+
m |= PIN_IO_DRIVE;
610613
break;
611614
case PIN_CONFIG_INPUT_SCHMITT_UV:
612615
ret = cv1800_pinctrl_schmitt2reg(pctrl, pin, arg);
613616
if (ret < 0)
614617
return ret;
615618
v &= ~PIN_IO_SCHMITT;
616619
v |= FIELD_PREP(PIN_IO_SCHMITT, ret);
620+
m |= PIN_IO_SCHMITT;
617621
break;
618622
case PIN_CONFIG_POWER_SOURCE:
619623
/* Ignore power source as it is always fixed */
620624
break;
621625
case PIN_CONFIG_SLEW_RATE:
622626
v &= ~PIN_IO_OUT_FAST_SLEW;
623627
v |= FIELD_PREP(PIN_IO_OUT_FAST_SLEW, arg);
628+
m |= PIN_IO_OUT_FAST_SLEW;
624629
break;
625630
case PIN_CONFIG_BIAS_BUS_HOLD:
626631
v &= ~PIN_IO_BUS_HOLD;
627632
v |= FIELD_PREP(PIN_IO_BUS_HOLD, arg);
633+
m |= PIN_IO_BUS_HOLD;
628634
break;
629635
default:
630636
return -ENOTSUPP;
631637
}
632638
}
633639

634640
*value = v;
641+
*mask = m;
635642

636643
return 0;
637644
}
638645

639646
static int cv1800_pin_set_config(struct cv1800_pinctrl *pctrl,
640647
unsigned int pin_id,
641-
u32 value)
648+
u32 value, u32 mask)
642649
{
643650
struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id);
644651
unsigned long flags;
645652
void __iomem *addr;
653+
u32 reg;
646654

647655
if (!pin)
648656
return -EINVAL;
649657

650658
addr = cv1800_pinctrl_get_component_addr(pctrl, &pin->conf);
651659

652660
raw_spin_lock_irqsave(&pctrl->lock, flags);
653-
writel(value, addr);
661+
reg = readl(addr);
662+
reg &= ~mask;
663+
reg |= value;
664+
writel(reg, addr);
654665
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
655666

656667
return 0;
@@ -662,16 +673,17 @@ static int cv1800_pconf_set(struct pinctrl_dev *pctldev,
662673
{
663674
struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
664675
struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id);
665-
u32 value;
676+
u32 value, mask;
666677

667678
if (!pin)
668679
return -ENODEV;
669680

670681
if (cv1800_pinconf_compute_config(pctrl, pin,
671-
configs, num_configs, &value))
682+
configs, num_configs,
683+
&value, &mask))
672684
return -ENOTSUPP;
673685

674-
return cv1800_pin_set_config(pctrl, pin_id, value);
686+
return cv1800_pin_set_config(pctrl, pin_id, value, mask);
675687
}
676688

677689
static int cv1800_pconf_group_set(struct pinctrl_dev *pctldev,
@@ -682,7 +694,7 @@ static int cv1800_pconf_group_set(struct pinctrl_dev *pctldev,
682694
struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
683695
const struct group_desc *group;
684696
const struct cv1800_pin_mux_config *pinmuxs;
685-
u32 value;
697+
u32 value, mask;
686698
int i;
687699

688700
group = pinctrl_generic_get_group(pctldev, gsel);
@@ -692,11 +704,12 @@ static int cv1800_pconf_group_set(struct pinctrl_dev *pctldev,
692704
pinmuxs = group->data;
693705

694706
if (cv1800_pinconf_compute_config(pctrl, pinmuxs[0].pin,
695-
configs, num_configs, &value))
707+
configs, num_configs,
708+
&value, &mask))
696709
return -ENOTSUPP;
697710

698711
for (i = 0; i < group->grp.npins; i++)
699-
cv1800_pin_set_config(pctrl, group->grp.pins[i], value);
712+
cv1800_pin_set_config(pctrl, group->grp.pins[i], value, mask);
700713

701714
return 0;
702715
}

0 commit comments

Comments
 (0)