in renesas/pinctrl-rzg2l.c [572:683]
static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev,
unsigned int _pin,
unsigned long *_configs,
unsigned int num_configs)
{
struct rzg2l_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
const struct pinctrl_pin_desc *pin = &pctrl->desc.pins[_pin];
unsigned int *pin_data = pin->drv_data;
enum pin_config_param param;
unsigned long flags;
void __iomem *addr;
u32 port_offset;
unsigned int i;
u32 cfg = 0;
u8 bit = 0;
if (!pin_data)
return -EINVAL;
if (*pin_data & RZG2L_SINGLE_PIN) {
port_offset = RZG2L_SINGLE_PIN_GET_PORT_OFFSET(*pin_data);
cfg = RZG2L_SINGLE_PIN_GET_CFGS(*pin_data);
bit = RZG2L_SINGLE_PIN_GET_BIT(*pin_data);
} else {
cfg = RZG2L_GPIO_PORT_GET_CFGS(*pin_data);
port_offset = RZG2L_PIN_ID_TO_PORT_OFFSET(_pin);
bit = RZG2L_PIN_ID_TO_PIN(_pin);
if (rzg2l_validate_gpio_pin(pctrl, *pin_data, RZG2L_PIN_ID_TO_PORT(_pin), bit))
return -EINVAL;
}
for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(_configs[i]);
switch (param) {
case PIN_CONFIG_INPUT_ENABLE: {
unsigned int arg =
pinconf_to_config_argument(_configs[i]);
if (!(cfg & PIN_CFG_IEN))
return -EINVAL;
rzg2l_rmw_pin_config(pctrl, IEN(port_offset), bit, IEN_MASK, !!arg);
break;
}
case PIN_CONFIG_POWER_SOURCE: {
unsigned int mV = pinconf_to_config_argument(_configs[i]);
u32 pwr_reg = 0x0;
if (mV != 1800 && mV != 3300)
return -EINVAL;
if (cfg & PIN_CFG_IO_VMC_SD0)
pwr_reg = SD_CH(0);
else if (cfg & PIN_CFG_IO_VMC_SD1)
pwr_reg = SD_CH(1);
else if (cfg & PIN_CFG_IO_VMC_QSPI)
pwr_reg = QSPI;
else
return -EINVAL;
addr = pctrl->base + pwr_reg;
spin_lock_irqsave(&pctrl->lock, flags);
writel((mV == 1800) ? PVDD_1800 : PVDD_3300, addr);
spin_unlock_irqrestore(&pctrl->lock, flags);
break;
}
case PIN_CONFIG_DRIVE_STRENGTH: {
unsigned int arg = pinconf_to_config_argument(_configs[i]);
unsigned int index;
if (!(cfg & PIN_CFG_IOLH_A))
return -EINVAL;
for (index = 0; index < ARRAY_SIZE(iolh_groupa_mA); index++) {
if (arg == iolh_groupa_mA[index])
break;
}
if (index >= ARRAY_SIZE(iolh_groupa_mA))
return -EINVAL;
rzg2l_rmw_pin_config(pctrl, IOLH(port_offset), bit, IOLH_MASK, index);
break;
}
case PIN_CONFIG_OUTPUT_IMPEDANCE_OHMS: {
unsigned int arg = pinconf_to_config_argument(_configs[i]);
unsigned int index;
if (!(cfg & PIN_CFG_IOLH_B))
return -EINVAL;
for (index = 0; index < ARRAY_SIZE(iolh_groupb_oi); index++) {
if (arg == iolh_groupb_oi[index])
break;
}
if (index >= ARRAY_SIZE(iolh_groupb_oi))
return -EINVAL;
rzg2l_rmw_pin_config(pctrl, IOLH(port_offset), bit, IOLH_MASK, index);
break;
}
default:
return -EOPNOTSUPP;
}
}
return 0;
}