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