/* The bits in CONFIG cell defined in binding doc*/ #define IMX_NO_PAD_CTL 0x80000000 /* no pin config need */ #define IMX_PAD_SION 0x40000000 /* set SION */
/* * first find the group of this node and check if we need create * config maps for pins
*/
grp = imx_pinctrl_find_group_by_name(pctldev, np->name); if (!grp) {
dev_err(ipctl->dev, "unable to find group for node %pOFn\n", np); return -EINVAL;
}
if (info->flags & IMX_USE_SCU) {
map_num += grp->grp.npins;
} else { for (i = 0; i < grp->grp.npins; i++) {
pin = &((struct imx_pin *)(grp->data))[i]; if (!(pin->conf.mmio.config & IMX_NO_PAD_CTL))
map_num++;
}
}
new_map = kmalloc_array(map_num, sizeof(struct pinctrl_map),
GFP_KERNEL); if (!new_map) return -ENOMEM;
/* create config map */
new_map++; for (i = j = 0; i < grp->grp.npins; i++) {
pin = &((struct imx_pin *)(grp->data))[i];
/* * We only create config maps for SCU pads or MMIO pads that * are not using the default config(a.k.a IMX_NO_PAD_CTL)
*/ if (!(info->flags & IMX_USE_SCU) &&
(pin->conf.mmio.config & IMX_NO_PAD_CTL)) continue;
if (info->flags & IMX_USE_SCU) { /* * For SCU case, we set mux and conf together * in one IPC call
*/
new_map[j].data.configs.configs =
(unsignedlong *)&pin->conf.scu;
new_map[j].data.configs.num_configs = 2;
} else {
new_map[j].data.configs.configs =
&pin->conf.mmio.config;
new_map[j].data.configs.num_configs = 1;
}
j++;
}
dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
(*map)->data.mux.function, (*map)->data.mux.group, map_num);
/* * If the select input value begins with 0xff, it's a quirky * select input and the value should be interpreted as below. * 31 23 15 7 0 * | 0xff | shift | width | select | * It's used to work around the problem that the select * input for some pin is not implemented in the select * input register but in some general purpose register. * We encode the select input value, width and shift of * the bit field into input_val cell of pin function ID * in device tree, and then decode them here for setting * up the select input bits in general purpose register.
*/ if (pin_mmio->input_val >> 24 == 0xff) {
u32 val = pin_mmio->input_val;
u8 select = val & 0xff;
u8 width = (val >> 8) & 0xff;
u8 shift = (val >> 16) & 0xff;
u32 mask = ((1 << width) - 1) << shift; /* * The input_reg[i] here is actually some IOMUXC general * purpose register, not regular select input register.
*/
val = readl(ipctl->base + pin_mmio->input_reg);
val &= ~mask;
val |= select << shift;
writel(val, ipctl->base + pin_mmio->input_reg);
} elseif (pin_mmio->input_reg) { /* * Regular select input register can never be at offset * 0, and we only print register value for regular case.
*/ if (ipctl->input_sel_base)
writel(pin_mmio->input_val, ipctl->input_sel_base +
pin_mmio->input_reg); else
writel(pin_mmio->input_val, ipctl->base +
pin_mmio->input_reg);
dev_dbg(ipctl->dev, "==>select_input: offset 0x%x val 0x%x\n",
pin_mmio->input_reg, pin_mmio->input_val);
}
/* * Configure the mux mode for each pin in the group for a specific * function.
*/
grp = pinctrl_generic_get_group(pctldev, group); if (!grp) return -EINVAL;
func = pinmux_generic_get_function(pctldev, selector); if (!func) return -EINVAL;
npins = grp->grp.npins;
dev_dbg(ipctl->dev, "enable function %s group %s\n",
func->func.name, grp->grp.name);
for (i = 0; i < npins; i++) { /* * For IMX_USE_SCU case, we postpone the mux setting * until config is set as we can set them together * in one IPC call
*/
pin = &((struct imx_pin *)(grp->data))[i]; if (!(info->flags & IMX_USE_SCU)) {
err = imx_pmx_set_one_pin_mmio(ipctl, pin); if (err) return err;
}
}
/* * the binding format is fsl,pins = <PIN_FUNC_ID CONFIG ...>, * do sanity check and calculate pins number * * First try legacy 'fsl,pins' property, then fall back to the * generic 'pinmux'. * * Note: for generic 'pinmux' case, there's no CONFIG part in * the binding format.
*/
list = of_get_property(np, "fsl,pins", &size); if (!list) {
list = of_get_property(np, "pinmux", &size); if (!list) {
dev_err(ipctl->dev, "no fsl,pins and pins property in node %pOF\n", np); return -EINVAL;
}
}
/* we do not check return since it's safe node passed down */ if (!size || size % pin_size) {
dev_err(ipctl->dev, "Invalid fsl,pins or pins property in node %pOF\n", np); return -EINVAL;
}
func = pinmux_generic_get_function(pctl, index); if (!func) return -EINVAL;
/* Initialise function */
func->func.name = np->name;
func->func.ngroups = of_get_child_count(np); if (func->func.ngroups == 0) {
dev_info(ipctl->dev, "no groups defined in %pOF\n", np); return -EINVAL;
}
/* * Check if the DT contains pins in the direct child nodes. This indicates the * newer DT format to store pins. This function returns true if the first found * fsl,pins property is in a child of np. Otherwise false is returned.
*/ staticbool imx_pinctrl_dt_is_flat_functions(struct device_node *np)
{
for_each_child_of_node_scoped(np, function_np) { if (of_property_present(function_np, "fsl,pins")) returntrue;
for_each_child_of_node_scoped(function_np, pinctrl_np) { if (of_property_present(pinctrl_np, "fsl,pins")) returnfalse;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.