// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2014-2018 Renesas Electronics Europe Limited * * Phil Edworthy <phil.edworthy@renesas.com> * Based on a driver originally written by Michel Pollet at Renesas.
*/
/* * The hardware manual describes two levels of multiplexing, but it's more * logical to think of the hardware as three levels, with level 3 consisting of * the multiplexing for Ethernet MDIO signals. * * Level 1 functions go from 0 to 9, with level 1 function '15' (0xf) specifying * that level 2 functions are used instead. Level 2 has a lot more options, * going from 0 to 61. Level 3 allows selection of MDIO functions which can be * floating, or one of seven internal peripherals. Unfortunately, there are two * level 2 functions that can select MDIO, and two MDIO channels so we have four * sets of level 3 functions. * * For this driver, we've compounded the numbers together, so: * 0 to 9 is level 1 * 10 to 71 is 10 + level 2 number * 72 to 79 is 72 + MDIO0 source for level 2 MDIO function. * 80 to 87 is 80 + MDIO0 source for level 2 MDIO_E1 function. * 88 to 95 is 88 + MDIO1 source for level 2 MDIO function. * 96 to 103 is 96 + MDIO1 source for level 2 MDIO_E1 function. * Examples: * Function 28 corresponds UART0 * Function 73 corresponds to MDIO0 to GMAC0 * * There are 170 configurable pins (called PL_GPIO in the datasheet).
*/
/* * Structure detailing the HW registers on the RZ/N1 devices. * Both the Level 1 mux registers and Level 2 mux registers have the same * structure. The only difference is that Level 2 has additional MDIO registers * at the end.
*/ struct rzn1_pinctrl_regs {
u32 conf[170];
u32 pad0[86];
u32 status_protect; /* 0x400 */ /* MDIO mux registers, level2 only */
u32 l2_mdio[2];
};
/** * struct rzn1_pmx_func - describes rzn1 pinmux functions * @name: the name of this specific function * @groups: corresponding pin groups * @num_groups: the number of groups
*/ struct rzn1_pmx_func { constchar *name; constchar **groups; unsignedint num_groups;
};
/** * struct rzn1_pin_group - describes an rzn1 pin group * @name: the name of this specific pin group * @func: the name of the function selected by this group * @npins: the number of pins in this group array, i.e. the number of * elements in .pins so we can iterate over that array * @pins: array of pins. Needed due to pinctrl_ops.get_group_pins() * @pin_ids: array of pin_ids, i.e. the value used to select the mux
*/ struct rzn1_pin_group { constchar *name; constchar *func; unsignedint npins; unsignedint *pins;
u8 *pin_ids;
};
staticvoid rzn1_hw_set_lock(struct rzn1_pinctrl *ipctl, u8 lock, u8 value)
{ /* * The pinmux configuration is locked by writing the physical address of * the status_protect register to itself. It is unlocked by writing the * address | 1.
*/ if (lock & LOCK_LEVEL1) {
u32 val = ipctl->lev1_protect_phys | !(value & LOCK_LEVEL1);
writel(val, &ipctl->lev1->status_protect);
}
if (lock & LOCK_LEVEL2) {
u32 val = ipctl->lev2_protect_phys | !(value & LOCK_LEVEL2);
writel(val, &ipctl->lev2->status_protect);
}
}
staticvoid rzn1_pinctrl_mdio_select(struct rzn1_pinctrl *ipctl, int mdio,
u32 func)
{ if (ipctl->mdio_func[mdio] >= 0 && ipctl->mdio_func[mdio] != func)
dev_warn(ipctl->dev, "conflicting setting for mdio%d!\n", mdio);
ipctl->mdio_func[mdio] = func;
dev_dbg(ipctl->dev, "setting mdio%d to %u\n", mdio, func);
writel(func, &ipctl->lev2->l2_mdio[mdio]);
}
/* * Using a composite pin description, set the hardware pinmux registers * with the corresponding values. * Make sure to unlock write protection and reset it afterward. * * NOTE: There is no protection for potential concurrency, it is assumed these * calls are serialized already.
*/ staticint rzn1_set_hw_pin_func(struct rzn1_pinctrl *ipctl, unsignedint pin,
u32 pin_config, u8 use_locks)
{
u32 l1_cache;
u32 l2_cache;
u32 l1;
u32 l2;
/* Level 3 MDIO multiplexing */ if (pin_config >= RZN1_FUNC_MDIO0_HIGHZ &&
pin_config <= RZN1_FUNC_MDIO1_E1_SWITCH) { int mdio_channel;
u32 mdio_func;
/* Note here, we do not allow anything past the MDIO Mux values */ if (pin >= ARRAY_SIZE(ipctl->lev1->conf) ||
pin_config >= RZN1_FUNC_MDIO0_HIGHZ) return -EINVAL;
/* If either configuration changes, we update both anyway */ if (l1 != l1_cache || l2 != l2_cache) {
writel(l1, &ipctl->lev1->conf[pin]);
writel(l2, &ipctl->lev2->conf[pin]);
}
/* * This function is called for each pinctl 'Function' node. * Sub-nodes can be used to describe multiple 'Groups' for the 'Function' * If there aren't any sub-nodes, the 'Group' is essentially the 'Function'. * Each 'Group' uses pinmux = <...> to detail the pins and data used to select * the functionality. Each 'Group' has optional pin configurations that apply * to all pins in the 'Group'.
*/ staticint rzn1_dt_node_to_map_one(struct pinctrl_dev *pctldev, struct device_node *np, struct pinctrl_map **map, unsignedint *num_maps)
{ struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); conststruct rzn1_pin_group *grp; unsignedlong *configs = NULL; unsignedint reserved_maps = *num_maps; unsignedint num_configs = 0; unsignedint reserve = 1; int ret;
grp = rzn1_pinctrl_find_group_by_name(ipctl, np->name); if (!grp) {
dev_err(ipctl->dev, "unable to find group for node %pOF\n", np);
return -EINVAL;
}
/* Get the group's pin configuration */
ret = pinconf_generic_parse_dt_config(np, pctldev, &configs,
&num_configs); if (ret < 0) {
dev_err(ipctl->dev, "%pOF: could not parse property\n", np);
return ret;
}
if (num_configs)
reserve++;
/* Increase the number of maps to cover this group */
ret = pinctrl_utils_reserve_map(pctldev, map, &reserved_maps, num_maps,
reserve); if (ret < 0) goto out;
/* Associate the group with the function */
ret = pinctrl_utils_add_map_mux(pctldev, map, &reserved_maps, num_maps,
grp->name, grp->func); if (ret < 0) goto out;
if (num_configs) { /* Associate the group's pin configuration with the group */
ret = pinctrl_utils_add_map_configs(pctldev, map,
&reserved_maps, num_maps, grp->name,
configs, num_configs,
PIN_MAP_TYPE_CONFIGS_GROUP); if (ret < 0) goto out;
}
dev_dbg(pctldev->dev, "maps: function %s group %s (%d pins)\n",
grp->func, grp->name, grp->npins);
/* * The binding format is * pinmux = <PIN_FUNC_ID CONFIG ...>, * do sanity check and calculate pins number
*/
list = of_get_property(np, RZN1_PINS_PROP, &size); if (!list) {
dev_err(ipctl->dev, "no " RZN1_PINS_PROP " property in node %pOF\n", np);
return -EINVAL;
}
if (!size) {
dev_err(ipctl->dev, "Invalid " RZN1_PINS_PROP " in node %pOF\n",
np);
/* Initialise function */
func->name = np->name;
func->num_groups = rzn1_pinctrl_count_function_groups(np); if (func->num_groups == 0) {
dev_err(ipctl->dev, "no groups defined in %pOF\n", np); return -EINVAL;
}
dev_dbg(ipctl->dev, "function %s has %d groups\n",
np->name, func->num_groups);
ipctl->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(ipctl->clk)) return PTR_ERR(ipctl->clk);
ret = clk_prepare_enable(ipctl->clk); if (ret) return ret;
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.