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