in pinctrl-single.c [996:1108]
static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
struct device_node *np,
struct pinctrl_map **map,
unsigned *num_maps,
const char **pgnames)
{
const char *name = "pinctrl-single,pins";
struct pcs_func_vals *vals;
int rows, *pins, found = 0, res = -ENOMEM, i, fsel, gsel;
struct pcs_function *function = NULL;
rows = pinctrl_count_index_with_args(np, name);
if (rows <= 0) {
dev_err(pcs->dev, "Invalid number of rows: %d\n", rows);
return -EINVAL;
}
vals = devm_kcalloc(pcs->dev, rows, sizeof(*vals), GFP_KERNEL);
if (!vals)
return -ENOMEM;
pins = devm_kcalloc(pcs->dev, rows, sizeof(*pins), GFP_KERNEL);
if (!pins)
goto free_vals;
for (i = 0; i < rows; i++) {
struct of_phandle_args pinctrl_spec;
unsigned int offset;
int pin;
res = pinctrl_parse_index_with_args(np, name, i, &pinctrl_spec);
if (res)
return res;
if (pinctrl_spec.args_count < 2 || pinctrl_spec.args_count > 3) {
dev_err(pcs->dev, "invalid args_count for spec: %i\n",
pinctrl_spec.args_count);
break;
}
offset = pinctrl_spec.args[0];
vals[found].reg = pcs->base + offset;
switch (pinctrl_spec.args_count) {
case 2:
vals[found].val = pinctrl_spec.args[1];
break;
case 3:
vals[found].val = (pinctrl_spec.args[1] | pinctrl_spec.args[2]);
break;
}
dev_dbg(pcs->dev, "%pOFn index: 0x%x value: 0x%x\n",
pinctrl_spec.np, offset, vals[found].val);
pin = pcs_get_pin_by_offset(pcs, offset);
if (pin < 0) {
dev_err(pcs->dev,
"could not add functions for %pOFn %ux\n",
np, offset);
break;
}
pins[found++] = pin;
}
pgnames[0] = np->name;
mutex_lock(&pcs->mutex);
fsel = pcs_add_function(pcs, &function, np->name, vals, found,
pgnames, 1);
if (fsel < 0) {
res = fsel;
goto free_pins;
}
gsel = pinctrl_generic_add_group(pcs->pctl, np->name, pins, found, pcs);
if (gsel < 0) {
res = gsel;
goto free_function;
}
(*map)->type = PIN_MAP_TYPE_MUX_GROUP;
(*map)->data.mux.group = np->name;
(*map)->data.mux.function = np->name;
if (PCS_HAS_PINCONF && function) {
res = pcs_parse_pinconf(pcs, np, function, map);
if (res == 0)
*num_maps = 2;
else if (res == -ENOTSUPP)
*num_maps = 1;
else
goto free_pingroups;
} else {
*num_maps = 1;
}
mutex_unlock(&pcs->mutex);
return 0;
free_pingroups:
pinctrl_generic_remove_group(pcs->pctl, gsel);
*num_maps = 1;
free_function:
pinmux_generic_remove_function(pcs->pctl, fsel);
free_pins:
mutex_unlock(&pcs->mutex);
devm_kfree(pcs->dev, pins);
free_vals:
devm_kfree(pcs->dev, vals);
return res;
}