1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> 4 */ 5 6 #include <common.h> 7 #include <dm.h> 8 #include <linux/compat.h> 9 #include <dm/pinctrl.h> 10 11 DECLARE_GLOBAL_DATA_PTR; 12 13 /** 14 * pinctrl_pin_name_to_selector() - return the pin selector for a pin 15 * 16 * @dev: pin controller device 17 * @pin: the pin name to look up 18 * @return: pin selector, or negative error code on failure 19 */ 20 static int pinctrl_pin_name_to_selector(struct udevice *dev, const char *pin) 21 { 22 const struct pinctrl_ops *ops = pinctrl_get_ops(dev); 23 unsigned npins, selector; 24 25 if (!ops->get_pins_count || !ops->get_pin_name) { 26 dev_dbg(dev, "get_pins_count or get_pin_name missing\n"); 27 return -ENOSYS; 28 } 29 30 npins = ops->get_pins_count(dev); 31 32 /* See if this pctldev has this pin */ 33 for (selector = 0; selector < npins; selector++) { 34 const char *pname = ops->get_pin_name(dev, selector); 35 36 if (!strcmp(pin, pname)) 37 return selector; 38 } 39 40 return -ENOSYS; 41 } 42 43 /** 44 * pinctrl_group_name_to_selector() - return the group selector for a group 45 * 46 * @dev: pin controller device 47 * @group: the pin group name to look up 48 * @return: pin group selector, or negative error code on failure 49 */ 50 static int pinctrl_group_name_to_selector(struct udevice *dev, 51 const char *group) 52 { 53 const struct pinctrl_ops *ops = pinctrl_get_ops(dev); 54 unsigned ngroups, selector; 55 56 if (!ops->get_groups_count || !ops->get_group_name) { 57 dev_dbg(dev, "get_groups_count or get_group_name missing\n"); 58 return -ENOSYS; 59 } 60 61 ngroups = ops->get_groups_count(dev); 62 63 /* See if this pctldev has this group */ 64 for (selector = 0; selector < ngroups; selector++) { 65 const char *gname = ops->get_group_name(dev, selector); 66 67 if (!strcmp(group, gname)) 68 return selector; 69 } 70 71 return -ENOSYS; 72 } 73 74 #if CONFIG_IS_ENABLED(PINMUX) 75 /** 76 * pinmux_func_name_to_selector() - return the function selector for a function 77 * 78 * @dev: pin controller device 79 * @function: the function name to look up 80 * @return: function selector, or negative error code on failure 81 */ 82 static int pinmux_func_name_to_selector(struct udevice *dev, 83 const char *function) 84 { 85 const struct pinctrl_ops *ops = pinctrl_get_ops(dev); 86 unsigned nfuncs, selector = 0; 87 88 if (!ops->get_functions_count || !ops->get_function_name) { 89 dev_dbg(dev, 90 "get_functions_count or get_function_name missing\n"); 91 return -ENOSYS; 92 } 93 94 nfuncs = ops->get_functions_count(dev); 95 96 /* See if this pctldev has this function */ 97 for (selector = 0; selector < nfuncs; selector++) { 98 const char *fname = ops->get_function_name(dev, selector); 99 100 if (!strcmp(function, fname)) 101 return selector; 102 } 103 104 return -ENOSYS; 105 } 106 107 /** 108 * pinmux_enable_setting() - enable pin-mux setting for a certain pin/group 109 * 110 * @dev: pin controller device 111 * @is_group: target of operation (true: pin group, false: pin) 112 * @selector: pin selector or group selector, depending on @is_group 113 * @func_selector: function selector 114 * @return: 0 on success, or negative error code on failure 115 */ 116 static int pinmux_enable_setting(struct udevice *dev, bool is_group, 117 unsigned selector, unsigned func_selector) 118 { 119 const struct pinctrl_ops *ops = pinctrl_get_ops(dev); 120 121 if (is_group) { 122 if (!ops->pinmux_group_set) { 123 dev_dbg(dev, "pinmux_group_set op missing\n"); 124 return -ENOSYS; 125 } 126 127 return ops->pinmux_group_set(dev, selector, func_selector); 128 } else { 129 if (!ops->pinmux_set) { 130 dev_dbg(dev, "pinmux_set op missing\n"); 131 return -ENOSYS; 132 } 133 return ops->pinmux_set(dev, selector, func_selector); 134 } 135 } 136 #else 137 static int pinmux_func_name_to_selector(struct udevice *dev, 138 const char *function) 139 { 140 return 0; 141 } 142 143 static int pinmux_enable_setting(struct udevice *dev, bool is_group, 144 unsigned selector, unsigned func_selector) 145 { 146 return 0; 147 } 148 #endif 149 150 #if CONFIG_IS_ENABLED(PINCONF) 151 /** 152 * pinconf_prop_name_to_param() - return parameter ID for a property name 153 * 154 * @dev: pin controller device 155 * @property: property name in DTS, such as "bias-pull-up", "slew-rate", etc. 156 * @default_value: return default value in case no value is specified in DTS 157 * @return: return pamater ID, or negative error code on failure 158 */ 159 static int pinconf_prop_name_to_param(struct udevice *dev, 160 const char *property, u32 *default_value) 161 { 162 const struct pinctrl_ops *ops = pinctrl_get_ops(dev); 163 const struct pinconf_param *p, *end; 164 165 if (!ops->pinconf_num_params || !ops->pinconf_params) { 166 dev_dbg(dev, "pinconf_num_params or pinconf_params missing\n"); 167 return -ENOSYS; 168 } 169 170 p = ops->pinconf_params; 171 end = p + ops->pinconf_num_params; 172 173 /* See if this pctldev supports this parameter */ 174 for (; p < end; p++) { 175 if (!strcmp(property, p->property)) { 176 *default_value = p->default_value; 177 return p->param; 178 } 179 } 180 181 return -ENOSYS; 182 } 183 184 /** 185 * pinconf_enable_setting() - apply pin configuration for a certain pin/group 186 * 187 * @dev: pin controller device 188 * @is_group: target of operation (true: pin group, false: pin) 189 * @selector: pin selector or group selector, depending on @is_group 190 * @param: configuration paramter 191 * @argument: argument taken by some configuration parameters 192 * @return: 0 on success, or negative error code on failure 193 */ 194 static int pinconf_enable_setting(struct udevice *dev, bool is_group, 195 unsigned selector, unsigned param, 196 u32 argument) 197 { 198 const struct pinctrl_ops *ops = pinctrl_get_ops(dev); 199 200 if (is_group) { 201 if (!ops->pinconf_group_set) { 202 dev_dbg(dev, "pinconf_group_set op missing\n"); 203 return -ENOSYS; 204 } 205 206 return ops->pinconf_group_set(dev, selector, param, 207 argument); 208 } else { 209 if (!ops->pinconf_set) { 210 dev_dbg(dev, "pinconf_set op missing\n"); 211 return -ENOSYS; 212 } 213 return ops->pinconf_set(dev, selector, param, argument); 214 } 215 } 216 #else 217 static int pinconf_prop_name_to_param(struct udevice *dev, 218 const char *property, u32 *default_value) 219 { 220 return -ENOSYS; 221 } 222 223 static int pinconf_enable_setting(struct udevice *dev, bool is_group, 224 unsigned selector, unsigned param, 225 u32 argument) 226 { 227 return 0; 228 } 229 #endif 230 231 /** 232 * pinctrl_generic_set_state_one() - set state for a certain pin/group 233 * Apply all pin multiplexing and pin configurations specified by @config 234 * for a given pin or pin group. 235 * 236 * @dev: pin controller device 237 * @config: pseudo device pointing to config node 238 * @is_group: target of operation (true: pin group, false: pin) 239 * @selector: pin selector or group selector, depending on @is_group 240 * @return: 0 on success, or negative error code on failure 241 */ 242 static int pinctrl_generic_set_state_one(struct udevice *dev, 243 struct udevice *config, 244 bool is_group, unsigned selector) 245 { 246 const void *fdt = gd->fdt_blob; 247 int node_offset = dev_of_offset(config); 248 const char *propname; 249 const void *value; 250 int prop_offset, len, func_selector, param, ret; 251 u32 arg, default_val; 252 253 for (prop_offset = fdt_first_property_offset(fdt, node_offset); 254 prop_offset > 0; 255 prop_offset = fdt_next_property_offset(fdt, prop_offset)) { 256 value = fdt_getprop_by_offset(fdt, prop_offset, 257 &propname, &len); 258 if (!value) 259 return -EINVAL; 260 261 if (!strcmp(propname, "function")) { 262 func_selector = pinmux_func_name_to_selector(dev, 263 value); 264 if (func_selector < 0) 265 return func_selector; 266 ret = pinmux_enable_setting(dev, is_group, 267 selector, 268 func_selector); 269 } else { 270 param = pinconf_prop_name_to_param(dev, propname, 271 &default_val); 272 if (param < 0) 273 continue; /* just skip unknown properties */ 274 275 if (len >= sizeof(fdt32_t)) 276 arg = fdt32_to_cpu(*(fdt32_t *)value); 277 else 278 arg = default_val; 279 280 ret = pinconf_enable_setting(dev, is_group, 281 selector, param, arg); 282 } 283 284 if (ret) 285 return ret; 286 } 287 288 return 0; 289 } 290 291 /** 292 * pinctrl_generic_set_state_subnode() - apply all settings in config node 293 * 294 * @dev: pin controller device 295 * @config: pseudo device pointing to config node 296 * @return: 0 on success, or negative error code on failure 297 */ 298 static int pinctrl_generic_set_state_subnode(struct udevice *dev, 299 struct udevice *config) 300 { 301 const void *fdt = gd->fdt_blob; 302 int node = dev_of_offset(config); 303 const char *subnode_target_type = "pins"; 304 bool is_group = false; 305 const char *name; 306 int strings_count, selector, i, ret; 307 308 strings_count = fdt_stringlist_count(fdt, node, subnode_target_type); 309 if (strings_count < 0) { 310 subnode_target_type = "groups"; 311 is_group = true; 312 strings_count = fdt_stringlist_count(fdt, node, 313 subnode_target_type); 314 if (strings_count < 0) { 315 /* skip this node; may contain config child nodes */ 316 return 0; 317 } 318 } 319 320 for (i = 0; i < strings_count; i++) { 321 name = fdt_stringlist_get(fdt, node, subnode_target_type, i, 322 NULL); 323 if (!name) 324 return -EINVAL; 325 326 if (is_group) 327 selector = pinctrl_group_name_to_selector(dev, name); 328 else 329 selector = pinctrl_pin_name_to_selector(dev, name); 330 if (selector < 0) 331 return selector; 332 333 ret = pinctrl_generic_set_state_one(dev, config, 334 is_group, selector); 335 if (ret) 336 return ret; 337 } 338 339 return 0; 340 } 341 342 int pinctrl_generic_set_state(struct udevice *dev, struct udevice *config) 343 { 344 struct udevice *child; 345 int ret; 346 347 ret = pinctrl_generic_set_state_subnode(dev, config); 348 if (ret) 349 return ret; 350 351 for (device_find_first_child(config, &child); 352 child; 353 device_find_next_child(&child)) { 354 ret = pinctrl_generic_set_state_subnode(dev, child); 355 if (ret) 356 return ret; 357 } 358 359 return 0; 360 } 361