uboot/drivers/pinctrl/pinctrl-generic.c
<<
>>
Prefs
   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 <dm/device_compat.h>
   9#include <linux/compat.h>
  10#include <dm/pinctrl.h>
  11
  12/**
  13 * pinctrl_pin_name_to_selector() - return the pin selector for a pin
  14 *
  15 * @dev: pin controller device
  16 * @pin: the pin name to look up
  17 * @return: pin selector, or negative error code on failure
  18 */
  19static int pinctrl_pin_name_to_selector(struct udevice *dev, const char *pin)
  20{
  21        const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
  22        unsigned npins, selector;
  23
  24        if (!ops->get_pins_count || !ops->get_pin_name) {
  25                dev_dbg(dev, "get_pins_count or get_pin_name missing\n");
  26                return -ENOSYS;
  27        }
  28
  29        npins = ops->get_pins_count(dev);
  30
  31        /* See if this pctldev has this pin */
  32        for (selector = 0; selector < npins; selector++) {
  33                const char *pname = ops->get_pin_name(dev, selector);
  34
  35                if (!strcmp(pin, pname))
  36                        return selector;
  37        }
  38
  39        return -ENOSYS;
  40}
  41
  42/**
  43 * pinctrl_group_name_to_selector() - return the group selector for a group
  44 *
  45 * @dev: pin controller device
  46 * @group: the pin group name to look up
  47 * @return: pin group selector, or negative error code on failure
  48 */
  49static int pinctrl_group_name_to_selector(struct udevice *dev,
  50                                          const char *group)
  51{
  52        const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
  53        unsigned ngroups, selector;
  54
  55        if (!ops->get_groups_count || !ops->get_group_name) {
  56                dev_dbg(dev, "get_groups_count or get_group_name missing\n");
  57                return -ENOSYS;
  58        }
  59
  60        ngroups = ops->get_groups_count(dev);
  61
  62        /* See if this pctldev has this group */
  63        for (selector = 0; selector < ngroups; selector++) {
  64                const char *gname = ops->get_group_name(dev, selector);
  65
  66                if (!strcmp(group, gname))
  67                        return selector;
  68        }
  69
  70        return -ENOSYS;
  71}
  72
  73#if CONFIG_IS_ENABLED(PINMUX)
  74/**
  75 * pinmux_func_name_to_selector() - return the function selector for a function
  76 *
  77 * @dev: pin controller device
  78 * @function: the function name to look up
  79 * @return: function selector, or negative error code on failure
  80 */
  81static int pinmux_func_name_to_selector(struct udevice *dev,
  82                                        const char *function)
  83{
  84        const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
  85        unsigned nfuncs, selector = 0;
  86
  87        if (!ops->get_functions_count || !ops->get_function_name) {
  88                dev_dbg(dev,
  89                        "get_functions_count or get_function_name missing\n");
  90                return -ENOSYS;
  91        }
  92
  93        nfuncs = ops->get_functions_count(dev);
  94
  95        /* See if this pctldev has this function */
  96        for (selector = 0; selector < nfuncs; selector++) {
  97                const char *fname = ops->get_function_name(dev, selector);
  98
  99                if (!strcmp(function, fname))
 100                        return selector;
 101        }
 102
 103        return -ENOSYS;
 104}
 105
 106/**
 107 * pinmux_enable_setting() - enable pin-mux setting for a certain pin/group
 108 *
 109 * @dev: pin controller device
 110 * @is_group: target of operation (true: pin group, false: pin)
 111 * @selector: pin selector or group selector, depending on @is_group
 112 * @func_selector: function selector
 113 * @return: 0 on success, or negative error code on failure
 114 */
 115static int pinmux_enable_setting(struct udevice *dev, bool is_group,
 116                                 unsigned selector, unsigned func_selector)
 117{
 118        const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
 119
 120        if (is_group) {
 121                if (!ops->pinmux_group_set) {
 122                        dev_dbg(dev, "pinmux_group_set op missing\n");
 123                        return -ENOSYS;
 124                }
 125
 126                return ops->pinmux_group_set(dev, selector, func_selector);
 127        } else {
 128                if (!ops->pinmux_set) {
 129                        dev_dbg(dev, "pinmux_set op missing\n");
 130                        return -ENOSYS;
 131                }
 132                return ops->pinmux_set(dev, selector, func_selector);
 133        }
 134}
 135#else
 136static int pinmux_func_name_to_selector(struct udevice *dev,
 137                                        const char *function)
 138{
 139        return 0;
 140}
 141
 142static int pinmux_enable_setting(struct udevice *dev, bool is_group,
 143                                 unsigned selector, unsigned func_selector)
 144{
 145        return 0;
 146}
 147#endif
 148
 149#if CONFIG_IS_ENABLED(PINCONF)
 150/**
 151 * pinconf_prop_name_to_param() - return parameter ID for a property name
 152 *
 153 * @dev: pin controller device
 154 * @property: property name in DTS, such as "bias-pull-up", "slew-rate", etc.
 155 * @default_value: return default value in case no value is specified in DTS
 156 * @return: return pamater ID, or negative error code on failure
 157 */
 158static int pinconf_prop_name_to_param(struct udevice *dev,
 159                                      const char *property, u32 *default_value)
 160{
 161        const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
 162        const struct pinconf_param *p, *end;
 163
 164        if (!ops->pinconf_num_params || !ops->pinconf_params) {
 165                dev_dbg(dev, "pinconf_num_params or pinconf_params missing\n");
 166                return -ENOSYS;
 167        }
 168
 169        p = ops->pinconf_params;
 170        end = p + ops->pinconf_num_params;
 171
 172        /* See if this pctldev supports this parameter */
 173        for (; p < end; p++) {
 174                if (!strcmp(property, p->property)) {
 175                        *default_value = p->default_value;
 176                        return p->param;
 177                }
 178        }
 179
 180        return -ENOSYS;
 181}
 182
 183/**
 184 * pinconf_enable_setting() - apply pin configuration for a certain pin/group
 185 *
 186 * @dev: pin controller device
 187 * @is_group: target of operation (true: pin group, false: pin)
 188 * @selector: pin selector or group selector, depending on @is_group
 189 * @param: configuration paramter
 190 * @argument: argument taken by some configuration parameters
 191 * @return: 0 on success, or negative error code on failure
 192 */
 193static int pinconf_enable_setting(struct udevice *dev, bool is_group,
 194                                  unsigned selector, unsigned param,
 195                                  u32 argument)
 196{
 197        const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
 198
 199        if (is_group) {
 200                if (!ops->pinconf_group_set) {
 201                        dev_dbg(dev, "pinconf_group_set op missing\n");
 202                        return -ENOSYS;
 203                }
 204
 205                return ops->pinconf_group_set(dev, selector, param,
 206                                              argument);
 207        } else {
 208                if (!ops->pinconf_set) {
 209                        dev_dbg(dev, "pinconf_set op missing\n");
 210                        return -ENOSYS;
 211                }
 212                return ops->pinconf_set(dev, selector, param, argument);
 213        }
 214}
 215#else
 216static int pinconf_prop_name_to_param(struct udevice *dev,
 217                                      const char *property, u32 *default_value)
 218{
 219        return -ENOSYS;
 220}
 221
 222static int pinconf_enable_setting(struct udevice *dev, bool is_group,
 223                                  unsigned selector, unsigned param,
 224                                  u32 argument)
 225{
 226        return 0;
 227}
 228#endif
 229
 230enum pinmux_subnode_type {
 231        PST_NONE = 0,
 232        PST_PIN,
 233        PST_GROUP,
 234        PST_PINMUX,
 235};
 236
 237static const char *alloc_name_with_prefix(const char *name, const char *prefix)
 238{
 239        if (prefix) {
 240                char *name_with_prefix = malloc(strlen(prefix) + strlen(name) + 1);
 241                if (name_with_prefix)
 242                        sprintf(name_with_prefix, "%s%s", prefix, name);
 243                return name_with_prefix;
 244        } else {
 245                return name;
 246        }
 247}
 248
 249static void free_name_with_prefix(const char *name_with_prefix, const char *prefix)
 250{
 251        if (prefix)
 252                free((char *)name_with_prefix);
 253}
 254
 255/**
 256 * pinctrl_generic_set_state_one() - set state for a certain pin/group
 257 * Apply all pin multiplexing and pin configurations specified by @config
 258 * for a given pin or pin group.
 259 *
 260 * @dev: pin controller device
 261 * @config: pseudo device pointing to config node
 262 * @subnode_type: target of operation (pin, group, or pin specified by a pinmux
 263 * group)
 264 * @selector: pin selector or group selector, depending on @subnode_type
 265 * @return: 0 on success, or negative error code on failure
 266 */
 267static int pinctrl_generic_set_state_one(struct udevice *dev,
 268                                         struct udevice *config,
 269                                         const char *prefix,
 270                                         enum pinmux_subnode_type subnode_type,
 271                                         unsigned selector)
 272{
 273        const char *function_propname;
 274        const char *propname;
 275        const void *value;
 276        struct ofprop property;
 277        int len, func_selector, param, ret;
 278        u32 arg, default_val;
 279
 280        assert(subnode_type != PST_NONE);
 281
 282        function_propname = alloc_name_with_prefix("function", prefix);
 283        if (!function_propname)
 284                return -ENOMEM;
 285
 286        dev_for_each_property(property, config) {
 287                value = dev_read_prop_by_prop(&property, &propname, &len);
 288                if (!value) {
 289                        free_name_with_prefix(function_propname, prefix);
 290                        return -EINVAL;
 291                }
 292
 293                /* pinmux subnodes already have their muxing set */
 294                if (subnode_type != PST_PINMUX &&
 295                    !strcmp(propname, function_propname)) {
 296                        func_selector = pinmux_func_name_to_selector(dev,
 297                                                                     value);
 298                        if (func_selector < 0) {
 299                                free_name_with_prefix(function_propname, prefix);
 300                                return func_selector;
 301                        }
 302                        ret = pinmux_enable_setting(dev,
 303                                                    subnode_type == PST_GROUP,
 304                                                    selector,
 305                                                    func_selector);
 306                } else {
 307                        param = pinconf_prop_name_to_param(dev, propname,
 308                                                           &default_val);
 309                        if (param < 0)
 310                                continue; /* just skip unknown properties */
 311
 312                        if (len >= sizeof(fdt32_t))
 313                                arg = fdt32_to_cpu(*(fdt32_t *)value);
 314                        else
 315                                arg = default_val;
 316
 317                        ret = pinconf_enable_setting(dev,
 318                                                     subnode_type == PST_GROUP,
 319                                                     selector, param, arg);
 320                }
 321
 322                if (ret) {
 323                        free_name_with_prefix(function_propname, prefix);
 324                        return ret;
 325                }
 326        }
 327
 328        free_name_with_prefix(function_propname, prefix);
 329        return 0;
 330}
 331
 332/**
 333 * pinctrl_generic_get_subnode_type() - determine whether there is a valid
 334 * pins, groups, or pinmux property in the config node
 335 *
 336 * @dev: pin controller device
 337 * @config: pseudo device pointing to config node
 338 * @count: number of specifiers contained within the property
 339 * @return: the type of the subnode, or PST_NONE
 340 */
 341static enum pinmux_subnode_type pinctrl_generic_get_subnode_type(struct udevice *dev,
 342                                                                 struct udevice *config,
 343                                                                 const char *prefix,
 344                                                                 int *count)
 345{
 346        const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
 347        const char *propname;
 348
 349        propname = alloc_name_with_prefix("pins", prefix);
 350        if (!propname)
 351                return -ENOMEM;
 352        *count = dev_read_string_count(config, propname);
 353        free_name_with_prefix(propname, prefix);
 354        if (*count >= 0)
 355                return PST_PIN;
 356
 357        propname = alloc_name_with_prefix("groups", prefix);
 358        if (!propname)
 359                return -ENOMEM;
 360        *count = dev_read_string_count(config, propname);
 361        free_name_with_prefix(propname, prefix);
 362        if (*count >= 0)
 363                return PST_GROUP;
 364
 365        if (ops->pinmux_property_set) {
 366                propname = alloc_name_with_prefix("pinmux", prefix);
 367                if (!propname)
 368                        return -ENOMEM;
 369                *count = dev_read_size(config, propname);
 370                free_name_with_prefix(propname, prefix);
 371                if (*count >= 0 && !(*count % sizeof(u32))) {
 372                        *count /= sizeof(u32);
 373                        return PST_PINMUX;
 374                }
 375        }
 376
 377        *count = 0;
 378        return PST_NONE;
 379}
 380
 381/**
 382 * pinctrl_generic_set_state_subnode() - apply all settings in config node
 383 *
 384 * @dev: pin controller device
 385 * @config: pseudo device pointing to config node
 386 * @prefix: device tree property prefix (e.g. vendor specific)
 387 * @return: 0 on success, or negative error code on failure
 388 */
 389static int pinctrl_generic_set_state_subnode(struct udevice *dev,
 390                                             struct udevice *config,
 391                                             const char *prefix)
 392{
 393        enum pinmux_subnode_type subnode_type;
 394        const char *propname;
 395        const char *name;
 396        int count, selector, i, ret, scratch;
 397        const u32 *pinmux_groups = NULL; /* prevent use-uninitialized warning */
 398
 399        subnode_type = pinctrl_generic_get_subnode_type(dev, config, prefix, &count);
 400
 401        debug("%s(%s, %s): count=%d\n", __func__, dev->name, config->name,
 402              count);
 403
 404        if (subnode_type == PST_PINMUX) {
 405                propname = alloc_name_with_prefix("pinmux", prefix);
 406                if (!propname)
 407                        return -ENOMEM;
 408                pinmux_groups = dev_read_prop(config, propname, &scratch);
 409                free_name_with_prefix(propname, prefix);
 410                if (!pinmux_groups)
 411                        return -EINVAL;
 412        }
 413
 414        for (i = 0; i < count; i++) {
 415                switch (subnode_type) {
 416                case PST_PIN:
 417                        propname = alloc_name_with_prefix("pins", prefix);
 418                        if (!propname)
 419                                return -ENOMEM;
 420                        ret = dev_read_string_index(config, propname, i, &name);
 421                        free_name_with_prefix(propname, prefix);
 422                        if (ret)
 423                                return ret;
 424                        selector = pinctrl_pin_name_to_selector(dev, name);
 425                        break;
 426                case PST_GROUP:
 427                        propname = alloc_name_with_prefix("groups", prefix);
 428                        if (!propname)
 429                                return -ENOMEM;
 430                        ret = dev_read_string_index(config, propname, i, &name);
 431                        free_name_with_prefix(propname, prefix);
 432                        if (ret)
 433                                return ret;
 434                        selector = pinctrl_group_name_to_selector(dev, name);
 435                        break;
 436                case PST_PINMUX: {
 437                        const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
 438                        u32 pinmux_group = fdt32_to_cpu(pinmux_groups[i]);
 439
 440                        /* Checked for in pinctrl_generic_get_subnode_type */
 441                        selector = ops->pinmux_property_set(dev, pinmux_group);
 442                        break;
 443                }
 444                case PST_NONE:
 445                default:
 446                        /* skip this node; may contain config child nodes */
 447                        return 0;
 448                }
 449
 450                if (selector < 0)
 451                        return selector;
 452
 453                ret = pinctrl_generic_set_state_one(dev, config, prefix,
 454                                                    subnode_type, selector);
 455                if (ret)
 456                        return ret;
 457        }
 458
 459        return 0;
 460}
 461
 462int pinctrl_generic_set_state_prefix(struct udevice *dev, struct udevice *config,
 463                                     const char *prefix)
 464{
 465        struct udevice *child;
 466        int ret;
 467
 468        ret = pinctrl_generic_set_state_subnode(dev, config, prefix);
 469        if (ret)
 470                return ret;
 471
 472        for (device_find_first_child(config, &child);
 473             child;
 474             device_find_next_child(&child)) {
 475                ret = pinctrl_generic_set_state_subnode(dev, child, prefix);
 476                if (ret)
 477                        return ret;
 478        }
 479
 480        return 0;
 481}
 482
 483int pinctrl_generic_set_state(struct udevice *dev, struct udevice *config)
 484{
 485        return pinctrl_generic_set_state_prefix(dev, config, NULL);
 486}
 487