pinctrl: sophgo: avoid to modify untouched bit when setting cv1800 pinconf
[ 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 <inochiama@gmail.com> Link: https://lore.kernel.org/20250211051801.470800-2-inochiama@gmail.com Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
baaf3084c2
commit
1dd943dfb5
@@ -574,10 +574,10 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
|
|||||||
struct cv1800_pin *pin,
|
struct cv1800_pin *pin,
|
||||||
unsigned long *configs,
|
unsigned long *configs,
|
||||||
unsigned int num_configs,
|
unsigned int num_configs,
|
||||||
u32 *value)
|
u32 *value, u32 *mask)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
u32 v = 0;
|
u32 v = 0, m = 0;
|
||||||
enum cv1800_pin_io_type type;
|
enum cv1800_pin_io_type type;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -596,10 +596,12 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
|
|||||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||||
v &= ~PIN_IO_PULLDOWN;
|
v &= ~PIN_IO_PULLDOWN;
|
||||||
v |= FIELD_PREP(PIN_IO_PULLDOWN, arg);
|
v |= FIELD_PREP(PIN_IO_PULLDOWN, arg);
|
||||||
|
m |= PIN_IO_PULLDOWN;
|
||||||
break;
|
break;
|
||||||
case PIN_CONFIG_BIAS_PULL_UP:
|
case PIN_CONFIG_BIAS_PULL_UP:
|
||||||
v &= ~PIN_IO_PULLUP;
|
v &= ~PIN_IO_PULLUP;
|
||||||
v |= FIELD_PREP(PIN_IO_PULLUP, arg);
|
v |= FIELD_PREP(PIN_IO_PULLUP, arg);
|
||||||
|
m |= PIN_IO_PULLUP;
|
||||||
break;
|
break;
|
||||||
case PIN_CONFIG_DRIVE_STRENGTH_UA:
|
case PIN_CONFIG_DRIVE_STRENGTH_UA:
|
||||||
ret = cv1800_pinctrl_oc2reg(pctrl, pin, arg);
|
ret = cv1800_pinctrl_oc2reg(pctrl, pin, arg);
|
||||||
@@ -607,6 +609,7 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
|
|||||||
return ret;
|
return ret;
|
||||||
v &= ~PIN_IO_DRIVE;
|
v &= ~PIN_IO_DRIVE;
|
||||||
v |= FIELD_PREP(PIN_IO_DRIVE, ret);
|
v |= FIELD_PREP(PIN_IO_DRIVE, ret);
|
||||||
|
m |= PIN_IO_DRIVE;
|
||||||
break;
|
break;
|
||||||
case PIN_CONFIG_INPUT_SCHMITT_UV:
|
case PIN_CONFIG_INPUT_SCHMITT_UV:
|
||||||
ret = cv1800_pinctrl_schmitt2reg(pctrl, pin, arg);
|
ret = cv1800_pinctrl_schmitt2reg(pctrl, pin, arg);
|
||||||
@@ -614,6 +617,7 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
|
|||||||
return ret;
|
return ret;
|
||||||
v &= ~PIN_IO_SCHMITT;
|
v &= ~PIN_IO_SCHMITT;
|
||||||
v |= FIELD_PREP(PIN_IO_SCHMITT, ret);
|
v |= FIELD_PREP(PIN_IO_SCHMITT, ret);
|
||||||
|
m |= PIN_IO_SCHMITT;
|
||||||
break;
|
break;
|
||||||
case PIN_CONFIG_POWER_SOURCE:
|
case PIN_CONFIG_POWER_SOURCE:
|
||||||
/* Ignore power source as it is always fixed */
|
/* Ignore power source as it is always fixed */
|
||||||
@@ -621,10 +625,12 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
|
|||||||
case PIN_CONFIG_SLEW_RATE:
|
case PIN_CONFIG_SLEW_RATE:
|
||||||
v &= ~PIN_IO_OUT_FAST_SLEW;
|
v &= ~PIN_IO_OUT_FAST_SLEW;
|
||||||
v |= FIELD_PREP(PIN_IO_OUT_FAST_SLEW, arg);
|
v |= FIELD_PREP(PIN_IO_OUT_FAST_SLEW, arg);
|
||||||
|
m |= PIN_IO_OUT_FAST_SLEW;
|
||||||
break;
|
break;
|
||||||
case PIN_CONFIG_BIAS_BUS_HOLD:
|
case PIN_CONFIG_BIAS_BUS_HOLD:
|
||||||
v &= ~PIN_IO_BUS_HOLD;
|
v &= ~PIN_IO_BUS_HOLD;
|
||||||
v |= FIELD_PREP(PIN_IO_BUS_HOLD, arg);
|
v |= FIELD_PREP(PIN_IO_BUS_HOLD, arg);
|
||||||
|
m |= PIN_IO_BUS_HOLD;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
@@ -632,17 +638,19 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
*value = v;
|
*value = v;
|
||||||
|
*mask = m;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cv1800_pin_set_config(struct cv1800_pinctrl *pctrl,
|
static int cv1800_pin_set_config(struct cv1800_pinctrl *pctrl,
|
||||||
unsigned int pin_id,
|
unsigned int pin_id,
|
||||||
u32 value)
|
u32 value, u32 mask)
|
||||||
{
|
{
|
||||||
struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id);
|
struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
void __iomem *addr;
|
void __iomem *addr;
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
if (!pin)
|
if (!pin)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -650,7 +658,10 @@ static int cv1800_pin_set_config(struct cv1800_pinctrl *pctrl,
|
|||||||
addr = cv1800_pinctrl_get_component_addr(pctrl, &pin->conf);
|
addr = cv1800_pinctrl_get_component_addr(pctrl, &pin->conf);
|
||||||
|
|
||||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||||
writel(value, addr);
|
reg = readl(addr);
|
||||||
|
reg &= ~mask;
|
||||||
|
reg |= value;
|
||||||
|
writel(reg, addr);
|
||||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -662,16 +673,17 @@ static int cv1800_pconf_set(struct pinctrl_dev *pctldev,
|
|||||||
{
|
{
|
||||||
struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||||
struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id);
|
struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id);
|
||||||
u32 value;
|
u32 value, mask;
|
||||||
|
|
||||||
if (!pin)
|
if (!pin)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (cv1800_pinconf_compute_config(pctrl, pin,
|
if (cv1800_pinconf_compute_config(pctrl, pin,
|
||||||
configs, num_configs, &value))
|
configs, num_configs,
|
||||||
|
&value, &mask))
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
|
|
||||||
return cv1800_pin_set_config(pctrl, pin_id, value);
|
return cv1800_pin_set_config(pctrl, pin_id, value, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cv1800_pconf_group_set(struct pinctrl_dev *pctldev,
|
static int cv1800_pconf_group_set(struct pinctrl_dev *pctldev,
|
||||||
@@ -682,7 +694,7 @@ static int cv1800_pconf_group_set(struct pinctrl_dev *pctldev,
|
|||||||
struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||||
const struct group_desc *group;
|
const struct group_desc *group;
|
||||||
const struct cv1800_pin_mux_config *pinmuxs;
|
const struct cv1800_pin_mux_config *pinmuxs;
|
||||||
u32 value;
|
u32 value, mask;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
group = pinctrl_generic_get_group(pctldev, gsel);
|
group = pinctrl_generic_get_group(pctldev, gsel);
|
||||||
@@ -692,11 +704,12 @@ static int cv1800_pconf_group_set(struct pinctrl_dev *pctldev,
|
|||||||
pinmuxs = group->data;
|
pinmuxs = group->data;
|
||||||
|
|
||||||
if (cv1800_pinconf_compute_config(pctrl, pinmuxs[0].pin,
|
if (cv1800_pinconf_compute_config(pctrl, pinmuxs[0].pin,
|
||||||
configs, num_configs, &value))
|
configs, num_configs,
|
||||||
|
&value, &mask))
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
|
|
||||||
for (i = 0; i < group->grp.npins; i++)
|
for (i = 0; i < group->grp.npins; i++)
|
||||||
cv1800_pin_set_config(pctrl, group->grp.pins[i], value);
|
cv1800_pin_set_config(pctrl, group->grp.pins[i], value, mask);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user