1*43722575SConor Dooley // SPDX-License-Identifier: GPL-2.0-only 2*43722575SConor Dooley 3*43722575SConor Dooley #define pr_fmt(fmt) "generic pinconfig core: " fmt 4*43722575SConor Dooley 5*43722575SConor Dooley #include <linux/array_size.h> 6*43722575SConor Dooley #include <linux/device.h> 7*43722575SConor Dooley #include <linux/module.h> 8*43722575SConor Dooley #include <linux/of.h> 9*43722575SConor Dooley #include <linux/slab.h> 10*43722575SConor Dooley 11*43722575SConor Dooley #include <linux/pinctrl/pinconf-generic.h> 12*43722575SConor Dooley #include <linux/pinctrl/pinconf.h> 13*43722575SConor Dooley #include <linux/pinctrl/pinctrl.h> 14*43722575SConor Dooley 15*43722575SConor Dooley #include "core.h" 16*43722575SConor Dooley #include "pinconf.h" 17*43722575SConor Dooley #include "pinctrl-utils.h" 18*43722575SConor Dooley #include "pinmux.h" 19*43722575SConor Dooley 20*43722575SConor Dooley static int pinctrl_generic_pins_function_dt_subnode_to_map(struct pinctrl_dev *pctldev, 21*43722575SConor Dooley struct device_node *parent, 22*43722575SConor Dooley struct device_node *np, 23*43722575SConor Dooley struct pinctrl_map **maps, 24*43722575SConor Dooley unsigned int *num_maps, 25*43722575SConor Dooley unsigned int *num_reserved_maps, 26*43722575SConor Dooley const char **group_names, 27*43722575SConor Dooley unsigned int ngroups) 28*43722575SConor Dooley { 29*43722575SConor Dooley struct device *dev = pctldev->dev; 30*43722575SConor Dooley const char **functions; 31*43722575SConor Dooley const char *group_name; 32*43722575SConor Dooley unsigned long *configs; 33*43722575SConor Dooley unsigned int num_configs, pin, *pins; 34*43722575SConor Dooley int npins, ret, reserve = 1; 35*43722575SConor Dooley 36*43722575SConor Dooley npins = of_property_count_u32_elems(np, "pins"); 37*43722575SConor Dooley 38*43722575SConor Dooley if (npins < 1) { 39*43722575SConor Dooley dev_err(dev, "invalid pinctrl group %pOFn.%pOFn %d\n", 40*43722575SConor Dooley parent, np, npins); 41*43722575SConor Dooley return npins; 42*43722575SConor Dooley } 43*43722575SConor Dooley 44*43722575SConor Dooley group_name = devm_kasprintf(dev, GFP_KERNEL, "%pOFn.%pOFn", parent, np); 45*43722575SConor Dooley if (!group_name) 46*43722575SConor Dooley return -ENOMEM; 47*43722575SConor Dooley 48*43722575SConor Dooley group_names[ngroups] = group_name; 49*43722575SConor Dooley 50*43722575SConor Dooley pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL); 51*43722575SConor Dooley if (!pins) 52*43722575SConor Dooley return -ENOMEM; 53*43722575SConor Dooley 54*43722575SConor Dooley functions = devm_kcalloc(dev, npins, sizeof(*functions), GFP_KERNEL); 55*43722575SConor Dooley if (!functions) 56*43722575SConor Dooley return -ENOMEM; 57*43722575SConor Dooley 58*43722575SConor Dooley for (int i = 0; i < npins; i++) { 59*43722575SConor Dooley ret = of_property_read_u32_index(np, "pins", i, &pin); 60*43722575SConor Dooley if (ret) 61*43722575SConor Dooley return ret; 62*43722575SConor Dooley 63*43722575SConor Dooley pins[i] = pin; 64*43722575SConor Dooley 65*43722575SConor Dooley ret = of_property_read_string(np, "function", &functions[i]); 66*43722575SConor Dooley if (ret) 67*43722575SConor Dooley return ret; 68*43722575SConor Dooley } 69*43722575SConor Dooley 70*43722575SConor Dooley ret = pinctrl_utils_reserve_map(pctldev, maps, num_reserved_maps, num_maps, reserve); 71*43722575SConor Dooley if (ret) 72*43722575SConor Dooley return ret; 73*43722575SConor Dooley 74*43722575SConor Dooley ret = pinctrl_utils_add_map_mux(pctldev, maps, num_reserved_maps, num_maps, group_name, 75*43722575SConor Dooley parent->name); 76*43722575SConor Dooley if (ret < 0) 77*43722575SConor Dooley return ret; 78*43722575SConor Dooley 79*43722575SConor Dooley ret = pinctrl_generic_add_group(pctldev, group_name, pins, npins, functions); 80*43722575SConor Dooley if (ret < 0) 81*43722575SConor Dooley return dev_err_probe(dev, ret, "failed to add group %s: %d\n", 82*43722575SConor Dooley group_name, ret); 83*43722575SConor Dooley 84*43722575SConor Dooley ret = pinconf_generic_parse_dt_config(np, pctldev, &configs, &num_configs); 85*43722575SConor Dooley if (ret) 86*43722575SConor Dooley return dev_err_probe(dev, ret, "failed to parse pin config of group %s\n", 87*43722575SConor Dooley group_name); 88*43722575SConor Dooley 89*43722575SConor Dooley if (num_configs == 0) 90*43722575SConor Dooley return 0; 91*43722575SConor Dooley 92*43722575SConor Dooley ret = pinctrl_utils_reserve_map(pctldev, maps, num_reserved_maps, num_maps, reserve); 93*43722575SConor Dooley if (ret) 94*43722575SConor Dooley return ret; 95*43722575SConor Dooley 96*43722575SConor Dooley ret = pinctrl_utils_add_map_configs(pctldev, maps, num_reserved_maps, num_maps, group_name, 97*43722575SConor Dooley configs, 98*43722575SConor Dooley num_configs, PIN_MAP_TYPE_CONFIGS_GROUP); 99*43722575SConor Dooley kfree(configs); 100*43722575SConor Dooley if (ret) 101*43722575SConor Dooley return ret; 102*43722575SConor Dooley 103*43722575SConor Dooley return 0; 104*43722575SConor Dooley }; 105*43722575SConor Dooley 106*43722575SConor Dooley /* 107*43722575SConor Dooley * For platforms that do not define groups or functions in the driver, but 108*43722575SConor Dooley * instead use the devicetree to describe them. This function will, unlike 109*43722575SConor Dooley * pinconf_generic_dt_node_to_map() etc which rely on driver defined groups 110*43722575SConor Dooley * and functions, create them in addition to parsing pinconf properties and 111*43722575SConor Dooley * adding mappings. 112*43722575SConor Dooley */ 113*43722575SConor Dooley int pinctrl_generic_pins_function_dt_node_to_map(struct pinctrl_dev *pctldev, 114*43722575SConor Dooley struct device_node *np, 115*43722575SConor Dooley struct pinctrl_map **maps, 116*43722575SConor Dooley unsigned int *num_maps) 117*43722575SConor Dooley { 118*43722575SConor Dooley struct device *dev = pctldev->dev; 119*43722575SConor Dooley struct device_node *child_np; 120*43722575SConor Dooley const char **group_names; 121*43722575SConor Dooley unsigned int num_reserved_maps = 0; 122*43722575SConor Dooley int ngroups = 0; 123*43722575SConor Dooley int ret; 124*43722575SConor Dooley 125*43722575SConor Dooley *maps = NULL; 126*43722575SConor Dooley *num_maps = 0; 127*43722575SConor Dooley 128*43722575SConor Dooley /* 129*43722575SConor Dooley * Check if this is actually the pins node, or a parent containing 130*43722575SConor Dooley * multiple pins nodes. 131*43722575SConor Dooley */ 132*43722575SConor Dooley if (!of_property_present(np, "pins")) 133*43722575SConor Dooley goto parent; 134*43722575SConor Dooley 135*43722575SConor Dooley group_names = devm_kcalloc(dev, 1, sizeof(*group_names), GFP_KERNEL); 136*43722575SConor Dooley if (!group_names) 137*43722575SConor Dooley return -ENOMEM; 138*43722575SConor Dooley 139*43722575SConor Dooley ret = pinctrl_generic_pins_function_dt_subnode_to_map(pctldev, np, np, 140*43722575SConor Dooley maps, num_maps, 141*43722575SConor Dooley &num_reserved_maps, 142*43722575SConor Dooley group_names, 143*43722575SConor Dooley ngroups); 144*43722575SConor Dooley if (ret) { 145*43722575SConor Dooley pinctrl_utils_free_map(pctldev, *maps, *num_maps); 146*43722575SConor Dooley return dev_err_probe(dev, ret, "error figuring out mappings for %s\n", np->name); 147*43722575SConor Dooley } 148*43722575SConor Dooley 149*43722575SConor Dooley ret = pinmux_generic_add_function(pctldev, np->name, group_names, 1, NULL); 150*43722575SConor Dooley if (ret < 0) { 151*43722575SConor Dooley pinctrl_utils_free_map(pctldev, *maps, *num_maps); 152*43722575SConor Dooley return dev_err_probe(dev, ret, "error adding function %s\n", np->name); 153*43722575SConor Dooley } 154*43722575SConor Dooley 155*43722575SConor Dooley return 0; 156*43722575SConor Dooley 157*43722575SConor Dooley parent: 158*43722575SConor Dooley for_each_available_child_of_node(np, child_np) 159*43722575SConor Dooley ngroups += 1; 160*43722575SConor Dooley 161*43722575SConor Dooley group_names = devm_kcalloc(dev, ngroups, sizeof(*group_names), GFP_KERNEL); 162*43722575SConor Dooley if (!group_names) 163*43722575SConor Dooley return -ENOMEM; 164*43722575SConor Dooley 165*43722575SConor Dooley ngroups = 0; 166*43722575SConor Dooley for_each_available_child_of_node_scoped(np, child_np) { 167*43722575SConor Dooley ret = pinctrl_generic_pins_function_dt_subnode_to_map(pctldev, np, child_np, 168*43722575SConor Dooley maps, num_maps, 169*43722575SConor Dooley &num_reserved_maps, 170*43722575SConor Dooley group_names, 171*43722575SConor Dooley ngroups); 172*43722575SConor Dooley if (ret) { 173*43722575SConor Dooley pinctrl_utils_free_map(pctldev, *maps, *num_maps); 174*43722575SConor Dooley return dev_err_probe(dev, ret, "error figuring out mappings for %s\n", 175*43722575SConor Dooley np->name); 176*43722575SConor Dooley } 177*43722575SConor Dooley 178*43722575SConor Dooley ngroups++; 179*43722575SConor Dooley } 180*43722575SConor Dooley 181*43722575SConor Dooley ret = pinmux_generic_add_function(pctldev, np->name, group_names, ngroups, NULL); 182*43722575SConor Dooley if (ret < 0) { 183*43722575SConor Dooley pinctrl_utils_free_map(pctldev, *maps, *num_maps); 184*43722575SConor Dooley return dev_err_probe(dev, ret, "error adding function %s\n", np->name); 185*43722575SConor Dooley } 186*43722575SConor Dooley 187*43722575SConor Dooley return 0; 188*43722575SConor Dooley } 189*43722575SConor Dooley EXPORT_SYMBOL_GPL(pinctrl_generic_pins_function_dt_node_to_map); 190