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