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