Commit d90a5a30dec16442fc64154e40018bdbb37776a9

Authored by Masahiro Yamada
Committed by Simon Glass
1 parent e6cabe4a6d

pinctrl: add pin control uclass support

This creates a new framework for handling of pin control devices,
i.e. devices that control different aspects of package pins.

This uclass handles pinmuxing and pin configuration; pinmuxing
controls switching among silicon blocks that share certain physical
pins, pin configuration handles electronic properties such as pin-
biasing, load capacitance etc.

This framework can support the same device tree bindings, but if you
do not need full interface support, you can disable some features to
reduce memory foot print.  Typically around 1.5KB is necessary to
include full-featured uclass support on ARM board (CONFIG_PINCTRL +
CONFIG_PINCTRL_FULL + CONFIG_PINCTRL_GENERIC + CONFIG_PINCTRL_PINMUX),
for example.

We are often limited on code size for SPL.  Besides, we still have
many boards that do not support device tree configuration.  The full
pinctrl, which requires OF_CONTROL, does not make sense for those
boards.  So, this framework also has a Do-It-Yourself (let's say
simple pinctrl) interface.  With CONFIG_PINCTRL_FULL disabled, the
uclass itself provides no systematic mechanism for identifying the
peripheral device, applying pinctrl settings, etc.  They must be
done in each low-level driver.  In return, you can save much memory
footprint and it might be useful especially for SPL.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Acked-by: Simon Glass <sjg@chromium.org>

Showing 9 changed files with 938 additions and 0 deletions Side-by-side Diff

... ... @@ -40,6 +40,8 @@
40 40  
41 41 source "drivers/pcmcia/Kconfig"
42 42  
  43 +source "drivers/pinctrl/Kconfig"
  44 +
43 45 source "drivers/power/Kconfig"
44 46  
45 47 source "drivers/ram/Kconfig"
1 1 obj-$(CONFIG_$(SPL_)DM) += core/
2 2 obj-$(CONFIG_$(SPL_)CLK) += clk/
3 3 obj-$(CONFIG_$(SPL_)LED) += led/
  4 +obj-$(CONFIG_$(SPL_)PINCTRL) += pinctrl/
4 5 obj-$(CONFIG_$(SPL_)RAM) += ram/
5 6  
6 7 ifdef CONFIG_SPL_BUILD
drivers/core/device.c
... ... @@ -15,6 +15,7 @@
15 15 #include <dm/device.h>
16 16 #include <dm/device-internal.h>
17 17 #include <dm/lists.h>
  18 +#include <dm/pinctrl.h>
18 19 #include <dm/platdata.h>
19 20 #include <dm/uclass.h>
20 21 #include <dm/uclass-internal.h>
... ... @@ -285,6 +286,9 @@
285 286 dev->seq = seq;
286 287  
287 288 dev->flags |= DM_FLAG_ACTIVATED;
  289 +
  290 + /* continue regardless of the result of pinctrl */
  291 + pinctrl_select_state(dev, "default");
288 292  
289 293 ret = uclass_pre_probe_device(dev);
290 294 if (ret)
drivers/pinctrl/Kconfig
  1 +#
  2 +# PINCTRL infrastructure and drivers
  3 +#
  4 +
  5 +menu "Pin controllers"
  6 +
  7 +config PINCTRL
  8 + bool "Support pin controllers"
  9 + depends on DM
  10 + help
  11 + This enables the basic support for pinctrl framework. You may want
  12 + to enable some more options depending on what you want to do.
  13 +
  14 +config PINCTRL_FULL
  15 + bool "Support full pin controllers"
  16 + depends on PINCTRL && OF_CONTROL
  17 + default y
  18 + help
  19 + This provides Linux-compatible device tree interface for the pinctrl
  20 + subsystem. This feature depends on device tree configuration because
  21 + it parses a device tree to look for the pinctrl device which the
  22 + peripheral device is associated with.
  23 +
  24 + If this option is disabled (it is the only possible choice for non-DT
  25 + boards), the pinctrl core provides no systematic mechanism for
  26 + identifying peripheral devices, applying needed pinctrl settings.
  27 + It is totally up to the implementation of each low-level driver.
  28 + You can save memory footprint in return for some limitations.
  29 +
  30 +config PINCTRL_GENERIC
  31 + bool "Support generic pin controllers"
  32 + depends on PINCTRL_FULL
  33 + default y
  34 + help
  35 + Say Y here if you want to use the pinctrl subsystem through the
  36 + generic DT interface. If enabled, some functions become available
  37 + to parse common properties such as "pins", "groups", "functions" and
  38 + some pin configuration parameters. It would be easier if you only
  39 + need the generic DT interface for pin muxing and pin configuration.
  40 + If you need to handle vendor-specific DT properties, you can disable
  41 + this option and implement your own set_state callback in the pinctrl
  42 + operations.
  43 +
  44 +config PINMUX
  45 + bool "Support pin multiplexing controllers"
  46 + depends on PINCTRL_GENERIC
  47 + default y
  48 + help
  49 + This option enables pin multiplexing through the generic pinctrl
  50 + framework.
  51 +
  52 +config PINCONF
  53 + bool "Support pin configuration controllers"
  54 + depends on PINCTRL_GENERIC
  55 + help
  56 + This option enables pin configuration through the generic pinctrl
  57 + framework.
  58 +
  59 +config SPL_PINCTRL
  60 + bool "Support pin controlloers in SPL"
  61 + depends on SPL && SPL_DM
  62 + help
  63 + This option is an SPL-variant of the PINCTRL option.
  64 + See the help of PINCTRL for details.
  65 +
  66 +config SPL_PINCTRL_FULL
  67 + bool "Support full pin controllers in SPL"
  68 + depends on SPL_PINCTRL && SPL_OF_CONTROL
  69 + default y
  70 + help
  71 + This option is an SPL-variant of the PINCTRL_FULL option.
  72 + See the help of PINCTRL_FULL for details.
  73 +
  74 +config SPL_PINCTRL_GENERIC
  75 + bool "Support generic pin controllers in SPL"
  76 + depends on SPL_PINCTRL_FULL
  77 + default y
  78 + help
  79 + This option is an SPL-variant of the PINCTRL_GENERIC option.
  80 + See the help of PINCTRL_GENERIC for details.
  81 +
  82 +config SPL_PINMUX
  83 + bool "Support pin multiplexing controllers in SPL"
  84 + depends on SPL_PINCTRL_GENERIC
  85 + default y
  86 + help
  87 + This option is an SPL-variant of the PINMUX option.
  88 + See the help of PINMUX for details.
  89 +
  90 +config SPL_PINCONF
  91 + bool "Support pin configuration controllers in SPL"
  92 + depends on SPL_PINCTRL_GENERIC
  93 + help
  94 + This option is an SPL-variant of the PINCONF option.
  95 + See the help of PINCONF for details.
  96 +
  97 +if PINCTRL || SPL_PINCTRL
  98 +
  99 +endif
  100 +
  101 +endmenu
drivers/pinctrl/Makefile
  1 +obj-y += pinctrl-uclass.o
  2 +obj-$(CONFIG_$(SPL_)PINCTRL_GENERIC) += pinctrl-generic.o
drivers/pinctrl/pinctrl-generic.c
  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_count_strings(fdt, node, subnode_target_type);
  310 + if (strings_count < 0) {
  311 + subnode_target_type = "groups";
  312 + is_group = true;
  313 + strings_count = fdt_count_strings(fdt, node,
  314 + subnode_target_type);
  315 + if (strings_count < 0)
  316 + return -EINVAL;
  317 + }
  318 +
  319 + for (i = 0; i < strings_count; i++) {
  320 + ret = fdt_get_string_index(fdt, node, subnode_target_type,
  321 + i, &name);
  322 + if (ret < 0)
  323 + return -EINVAL;
  324 +
  325 + if (is_group)
  326 + selector = pinctrl_group_name_to_selector(dev, name);
  327 + else
  328 + selector = pinctrl_pin_name_to_selector(dev, name);
  329 + if (selector < 0)
  330 + return selector;
  331 +
  332 + ret = pinctrl_generic_set_state_one(dev, config,
  333 + is_group, selector);
  334 + if (ret)
  335 + return ret;
  336 + }
  337 +
  338 + return 0;
  339 +}
  340 +
  341 +int pinctrl_generic_set_state(struct udevice *dev, struct udevice *config)
  342 +{
  343 + struct udevice *child;
  344 + int ret;
  345 +
  346 + ret = pinctrl_generic_set_state_subnode(dev, config);
  347 + if (ret)
  348 + return ret;
  349 +
  350 + for (device_find_first_child(config, &child);
  351 + child;
  352 + device_find_next_child(&child)) {
  353 + ret = pinctrl_generic_set_state_subnode(dev, child);
  354 + if (ret)
  355 + return ret;
  356 + }
  357 +
  358 + return 0;
  359 +}
drivers/pinctrl/pinctrl-uclass.c
  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 <libfdt.h>
  9 +#include <linux/err.h>
  10 +#include <linux/list.h>
  11 +#include <dm/device.h>
  12 +#include <dm/lists.h>
  13 +#include <dm/pinctrl.h>
  14 +#include <dm/uclass.h>
  15 +
  16 +DECLARE_GLOBAL_DATA_PTR;
  17 +
  18 +#if CONFIG_IS_ENABLED(PINCTRL_FULL)
  19 +/**
  20 + * pinctrl_config_one() - apply pinctrl settings for a single node
  21 + *
  22 + * @config: pin configuration node
  23 + * @return: 0 on success, or negative error code on failure
  24 + */
  25 +static int pinctrl_config_one(struct udevice *config)
  26 +{
  27 + struct udevice *pctldev;
  28 + const struct pinctrl_ops *ops;
  29 +
  30 + pctldev = config;
  31 + for (;;) {
  32 + pctldev = dev_get_parent(pctldev);
  33 + if (!pctldev) {
  34 + dev_err(config, "could not find pctldev\n");
  35 + return -EINVAL;
  36 + }
  37 + if (pctldev->uclass->uc_drv->id == UCLASS_PINCTRL)
  38 + break;
  39 + }
  40 +
  41 + ops = pinctrl_get_ops(pctldev);
  42 + return ops->set_state(pctldev, config);
  43 +}
  44 +
  45 +/**
  46 + * pinctrl_select_state_full() - full implementation of pinctrl_select_state
  47 + *
  48 + * @dev: peripheral device
  49 + * @statename: state name, like "default"
  50 + * @return: 0 on success, or negative error code on failure
  51 + */
  52 +static int pinctrl_select_state_full(struct udevice *dev, const char *statename)
  53 +{
  54 + const void *fdt = gd->fdt_blob;
  55 + int node = dev->of_offset;
  56 + char propname[32]; /* long enough */
  57 + const fdt32_t *list;
  58 + uint32_t phandle;
  59 + int config_node;
  60 + struct udevice *config;
  61 + int state, size, i, ret;
  62 +
  63 + state = fdt_find_string(fdt, node, "pinctrl-names", statename);
  64 + if (state < 0) {
  65 + char *end;
  66 + /*
  67 + * If statename is not found in "pinctrl-names",
  68 + * assume statename is just the integer state ID.
  69 + */
  70 + state = simple_strtoul(statename, &end, 10);
  71 + if (*end)
  72 + return -EINVAL;
  73 + }
  74 +
  75 + snprintf(propname, sizeof(propname), "pinctrl-%d", state);
  76 + list = fdt_getprop(fdt, node, propname, &size);
  77 + if (!list)
  78 + return -EINVAL;
  79 +
  80 + size /= sizeof(*list);
  81 + for (i = 0; i < size; i++) {
  82 + phandle = fdt32_to_cpu(*list++);
  83 +
  84 + config_node = fdt_node_offset_by_phandle(fdt, phandle);
  85 + if (config_node < 0) {
  86 + dev_err(dev, "prop %s index %d invalid phandle\n",
  87 + propname, i);
  88 + return -EINVAL;
  89 + }
  90 + ret = uclass_get_device_by_of_offset(UCLASS_PINCONFIG,
  91 + config_node, &config);
  92 + if (ret)
  93 + return ret;
  94 +
  95 + ret = pinctrl_config_one(config);
  96 + if (ret)
  97 + return ret;
  98 + }
  99 +
  100 + return 0;
  101 +}
  102 +
  103 +/**
  104 + * pinconfig_post-bind() - post binding for PINCONFIG uclass
  105 + * Recursively bind its children as pinconfig devices.
  106 + *
  107 + * @dev: pinconfig device
  108 + * @return: 0 on success, or negative error code on failure
  109 + */
  110 +static int pinconfig_post_bind(struct udevice *dev)
  111 +{
  112 + const void *fdt = gd->fdt_blob;
  113 + int offset = dev->of_offset;
  114 + const char *name;
  115 + int ret;
  116 +
  117 + for (offset = fdt_first_subnode(fdt, offset);
  118 + offset > 0;
  119 + offset = fdt_next_subnode(fdt, offset)) {
  120 + /*
  121 + * If this node has "compatible" property, this is not
  122 + * a pin configuration node, but a normal device. skip.
  123 + */
  124 + fdt_get_property(fdt, offset, "compatible", &ret);
  125 + if (ret >= 0)
  126 + continue;
  127 +
  128 + if (ret != -FDT_ERR_NOTFOUND)
  129 + return ret;
  130 +
  131 + name = fdt_get_name(fdt, offset, NULL);
  132 + if (!name)
  133 + return -EINVAL;
  134 + ret = device_bind_driver_to_node(dev, "pinconfig", name,
  135 + offset, NULL);
  136 + if (ret)
  137 + return ret;
  138 + }
  139 +
  140 + return 0;
  141 +}
  142 +
  143 +UCLASS_DRIVER(pinconfig) = {
  144 + .id = UCLASS_PINCONFIG,
  145 + .post_bind = pinconfig_post_bind,
  146 + .name = "pinconfig",
  147 +};
  148 +
  149 +U_BOOT_DRIVER(pinconfig_generic) = {
  150 + .name = "pinconfig",
  151 + .id = UCLASS_PINCONFIG,
  152 +};
  153 +
  154 +#else
  155 +static int pinctrl_select_state_full(struct udevice *dev, const char *statename)
  156 +{
  157 + return -ENODEV;
  158 +}
  159 +
  160 +static int pinconfig_post_bind(struct udevice *dev)
  161 +{
  162 + return 0;
  163 +}
  164 +#endif
  165 +
  166 +/**
  167 + * pinctrl_select_state_simple() - simple implementation of pinctrl_select_state
  168 + *
  169 + * @dev: peripheral device
  170 + * @return: 0 on success, or negative error code on failure
  171 + */
  172 +static int pinctrl_select_state_simple(struct udevice *dev)
  173 +{
  174 + struct udevice *pctldev;
  175 + struct pinctrl_ops *ops;
  176 + int ret;
  177 +
  178 + /*
  179 + * For simplicity, assume the first device of PINCTRL uclass
  180 + * is the correct one. This is most likely OK as there is
  181 + * usually only one pinctrl device on the system.
  182 + */
  183 + ret = uclass_get_device(UCLASS_PINCTRL, 0, &pctldev);
  184 + if (ret)
  185 + return ret;
  186 +
  187 + ops = pinctrl_get_ops(pctldev);
  188 + if (!ops->set_state_simple) {
  189 + dev_dbg(dev, "set_state_simple op missing\n");
  190 + return -ENOSYS;
  191 + }
  192 +
  193 + return ops->set_state_simple(pctldev, dev);
  194 +}
  195 +
  196 +int pinctrl_select_state(struct udevice *dev, const char *statename)
  197 +{
  198 + /*
  199 + * Try full-implemented pinctrl first.
  200 + * If it fails or is not implemented, try simple one.
  201 + */
  202 + if (pinctrl_select_state_full(dev, statename))
  203 + return pinctrl_select_state_simple(dev);
  204 +
  205 + return 0;
  206 +}
  207 +
  208 +/**
  209 + * pinconfig_post-bind() - post binding for PINCTRL uclass
  210 + * Recursively bind child nodes as pinconfig devices in case of full pinctrl.
  211 + *
  212 + * @dev: pinctrl device
  213 + * @return: 0 on success, or negative error code on failure
  214 + */
  215 +static int pinctrl_post_bind(struct udevice *dev)
  216 +{
  217 + const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
  218 +
  219 + if (!ops) {
  220 + dev_dbg(dev, "ops is not set. Do not bind.\n");
  221 + return -EINVAL;
  222 + }
  223 +
  224 + /*
  225 + * If set_state callback is set, we assume this pinctrl driver is the
  226 + * full implementation. In this case, its child nodes should be bound
  227 + * so that peripheral devices can easily search in parent devices
  228 + * during later DT-parsing.
  229 + */
  230 + if (ops->set_state)
  231 + return pinconfig_post_bind(dev);
  232 +
  233 + return 0;
  234 +}
  235 +
  236 +UCLASS_DRIVER(pinctrl) = {
  237 + .id = UCLASS_PINCTRL,
  238 + .post_bind = pinctrl_post_bind,
  239 + .name = "pinctrl",
  240 +};
include/dm/pinctrl.h
  1 +/*
  2 + * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
  3 + *
  4 + * SPDX-License-Identifier: GPL-2.0+
  5 + */
  6 +
  7 +#ifndef __PINCTRL_H
  8 +#define __PINCTRL_H
  9 +
  10 +/**
  11 + * struct pinconf_param - pin config parameters
  12 + *
  13 + * @property: property name in DT nodes
  14 + * @param: ID for this config parameter
  15 + * @default_value: default value for this config parameter used in case
  16 + * no value is specified in DT nodes
  17 + */
  18 +struct pinconf_param {
  19 + const char * const property;
  20 + unsigned int param;
  21 + u32 default_value;
  22 +};
  23 +
  24 +/**
  25 + * struct pinctrl_ops - pin control operations, to be implemented by
  26 + * pin controller drivers.
  27 + *
  28 + * The @set_state is the only mandatory operation. You can implement your
  29 + * pinctrl driver with its own @set_state. In this case, the other callbacks
  30 + * are not required. Otherwise, generic pinctrl framework is also available;
  31 + * use pinctrl_generic_set_state for @set_state, and implement other operations
  32 + * depending on your necessity.
  33 + *
  34 + * @get_pins_count: return number of selectable named pins available
  35 + * in this driver. (necessary to parse "pins" property in DTS)
  36 + * @get_pin_name: return the pin name of the pin selector,
  37 + * called by the core to figure out which pin it shall do
  38 + * operations to. (necessary to parse "pins" property in DTS)
  39 + * @get_groups_count: return number of selectable named groups available
  40 + * in this driver. (necessary to parse "groups" property in DTS)
  41 + * @get_group_name: return the group name of the group selector,
  42 + * called by the core to figure out which pin group it shall do
  43 + * operations to. (necessary to parse "groups" property in DTS)
  44 + * @get_functions_count: return number of selectable named functions available
  45 + * in this driver. (necessary for pin-muxing)
  46 + * @get_function_name: return the function name of the muxing selector,
  47 + * called by the core to figure out which mux setting it shall map a
  48 + * certain device to. (necessary for pin-muxing)
  49 + * @pinmux_set: enable a certain muxing function with a certain pin.
  50 + * The @func_selector selects a certain function whereas @pin_selector
  51 + * selects a certain pin to be used. On simple controllers one of them
  52 + * may be ignored. (necessary for pin-muxing against a single pin)
  53 + * @pinmux_group_set: enable a certain muxing function with a certain pin
  54 + * group. The @func_selector selects a certain function whereas
  55 + * @group_selector selects a certain set of pins to be used. On simple
  56 + * controllers one of them may be ignored.
  57 + * (necessary for pin-muxing against a pin group)
  58 + * @pinconf_num_params: number of driver-specific parameters to be parsed
  59 + * from device trees (necessary for pin-configuration)
  60 + * @pinconf_params: list of driver_specific parameters to be parsed from
  61 + * device trees (necessary for pin-configuration)
  62 + * @pinconf_set: configure an individual pin with a given parameter.
  63 + * (necessary for pin-configuration against a single pin)
  64 + * @pinconf_group_set: configure all pins in a group with a given parameter.
  65 + * (necessary for pin-configuration against a pin group)
  66 + * @set_state: do pinctrl operations specified by @config, a pseudo device
  67 + * pointing a config node. (necessary for pinctrl_full)
  68 + * @set_state_simple: do needed pinctrl operations for a peripherl @periph.
  69 + * (necessary for pinctrl_simple)
  70 + */
  71 +struct pinctrl_ops {
  72 + int (*get_pins_count)(struct udevice *dev);
  73 + const char *(*get_pin_name)(struct udevice *dev, unsigned selector);
  74 + int (*get_groups_count)(struct udevice *dev);
  75 + const char *(*get_group_name)(struct udevice *dev, unsigned selector);
  76 + int (*get_functions_count)(struct udevice *dev);
  77 + const char *(*get_function_name)(struct udevice *dev,
  78 + unsigned selector);
  79 + int (*pinmux_set)(struct udevice *dev, unsigned pin_selector,
  80 + unsigned func_selector);
  81 + int (*pinmux_group_set)(struct udevice *dev, unsigned group_selector,
  82 + unsigned func_selector);
  83 + unsigned int pinconf_num_params;
  84 + const struct pinconf_param *pinconf_params;
  85 + int (*pinconf_set)(struct udevice *dev, unsigned pin_selector,
  86 + unsigned param, unsigned argument);
  87 + int (*pinconf_group_set)(struct udevice *dev, unsigned group_selector,
  88 + unsigned param, unsigned argument);
  89 + int (*set_state)(struct udevice *dev, struct udevice *config);
  90 + int (*set_state_simple)(struct udevice *dev, struct udevice *periph);
  91 +};
  92 +
  93 +#define pinctrl_get_ops(dev) ((struct pinctrl_ops *)(dev)->driver->ops)
  94 +
  95 +/**
  96 + * Generic pin configuration paramters
  97 + *
  98 + * @PIN_CONFIG_BIAS_DISABLE: disable any pin bias on the pin, a
  99 + * transition from say pull-up to pull-down implies that you disable
  100 + * pull-up in the process, this setting disables all biasing.
  101 + * @PIN_CONFIG_BIAS_HIGH_IMPEDANCE: the pin will be set to a high impedance
  102 + * mode, also know as "third-state" (tristate) or "high-Z" or "floating".
  103 + * On output pins this effectively disconnects the pin, which is useful
  104 + * if for example some other pin is going to drive the signal connected
  105 + * to it for a while. Pins used for input are usually always high
  106 + * impedance.
  107 + * @PIN_CONFIG_BIAS_BUS_HOLD: the pin will be set to weakly latch so that it
  108 + * weakly drives the last value on a tristate bus, also known as a "bus
  109 + * holder", "bus keeper" or "repeater". This allows another device on the
  110 + * bus to change the value by driving the bus high or low and switching to
  111 + * tristate. The argument is ignored.
  112 + * @PIN_CONFIG_BIAS_PULL_UP: the pin will be pulled up (usually with high
  113 + * impedance to VDD). If the argument is != 0 pull-up is enabled,
  114 + * if it is 0, pull-up is total, i.e. the pin is connected to VDD.
  115 + * @PIN_CONFIG_BIAS_PULL_DOWN: the pin will be pulled down (usually with high
  116 + * impedance to GROUND). If the argument is != 0 pull-down is enabled,
  117 + * if it is 0, pull-down is total, i.e. the pin is connected to GROUND.
  118 + * @PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: the pin will be pulled up or down based
  119 + * on embedded knowledge of the controller hardware, like current mux
  120 + * function. The pull direction and possibly strength too will normally
  121 + * be decided completely inside the hardware block and not be readable
  122 + * from the kernel side.
  123 + * If the argument is != 0 pull up/down is enabled, if it is 0, the
  124 + * configuration is ignored. The proper way to disable it is to use
  125 + * @PIN_CONFIG_BIAS_DISABLE.
  126 + * @PIN_CONFIG_DRIVE_PUSH_PULL: the pin will be driven actively high and
  127 + * low, this is the most typical case and is typically achieved with two
  128 + * active transistors on the output. Setting this config will enable
  129 + * push-pull mode, the argument is ignored.
  130 + * @PIN_CONFIG_DRIVE_OPEN_DRAIN: the pin will be driven with open drain (open
  131 + * collector) which means it is usually wired with other output ports
  132 + * which are then pulled up with an external resistor. Setting this
  133 + * config will enable open drain mode, the argument is ignored.
  134 + * @PIN_CONFIG_DRIVE_OPEN_SOURCE: the pin will be driven with open source
  135 + * (open emitter). Setting this config will enable open source mode, the
  136 + * argument is ignored.
  137 + * @PIN_CONFIG_DRIVE_STRENGTH: the pin will sink or source at most the current
  138 + * passed as argument. The argument is in mA.
  139 + * @PIN_CONFIG_INPUT_ENABLE: enable the pin's input. Note that this does not
  140 + * affect the pin's ability to drive output. 1 enables input, 0 disables
  141 + * input.
  142 + * @PIN_CONFIG_INPUT_SCHMITT_ENABLE: control schmitt-trigger mode on the pin.
  143 + * If the argument != 0, schmitt-trigger mode is enabled. If it's 0,
  144 + * schmitt-trigger mode is disabled.
  145 + * @PIN_CONFIG_INPUT_SCHMITT: this will configure an input pin to run in
  146 + * schmitt-trigger mode. If the schmitt-trigger has adjustable hysteresis,
  147 + * the threshold value is given on a custom format as argument when
  148 + * setting pins to this mode.
  149 + * @PIN_CONFIG_INPUT_DEBOUNCE: this will configure the pin to debounce mode,
  150 + * which means it will wait for signals to settle when reading inputs. The
  151 + * argument gives the debounce time in usecs. Setting the
  152 + * argument to zero turns debouncing off.
  153 + * @PIN_CONFIG_POWER_SOURCE: if the pin can select between different power
  154 + * supplies, the argument to this parameter (on a custom format) tells
  155 + * the driver which alternative power source to use.
  156 + * @PIN_CONFIG_SLEW_RATE: if the pin can select slew rate, the argument to
  157 + * this parameter (on a custom format) tells the driver which alternative
  158 + * slew rate to use.
  159 + * @PIN_CONFIG_LOW_POWER_MODE: this will configure the pin for low power
  160 + * operation, if several modes of operation are supported these can be
  161 + * passed in the argument on a custom form, else just use argument 1
  162 + * to indicate low power mode, argument 0 turns low power mode off.
  163 + * @PIN_CONFIG_OUTPUT: this will configure the pin as an output. Use argument
  164 + * 1 to indicate high level, argument 0 to indicate low level. (Please
  165 + * see Documentation/pinctrl.txt, section "GPIO mode pitfalls" for a
  166 + * discussion around this parameter.)
  167 + * @PIN_CONFIG_END: this is the last enumerator for pin configurations, if
  168 + * you need to pass in custom configurations to the pin controller, use
  169 + * PIN_CONFIG_END+1 as the base offset.
  170 + */
  171 +#define PIN_CONFIG_BIAS_DISABLE 0
  172 +#define PIN_CONFIG_BIAS_HIGH_IMPEDANCE 1
  173 +#define PIN_CONFIG_BIAS_BUS_HOLD 2
  174 +#define PIN_CONFIG_BIAS_PULL_UP 3
  175 +#define PIN_CONFIG_BIAS_PULL_DOWN 4
  176 +#define PIN_CONFIG_BIAS_PULL_PIN_DEFAULT 5
  177 +#define PIN_CONFIG_DRIVE_PUSH_PULL 6
  178 +#define PIN_CONFIG_DRIVE_OPEN_DRAIN 7
  179 +#define PIN_CONFIG_DRIVE_OPEN_SOURCE 8
  180 +#define PIN_CONFIG_DRIVE_STRENGTH 9
  181 +#define PIN_CONFIG_INPUT_ENABLE 10
  182 +#define PIN_CONFIG_INPUT_SCHMITT_ENABLE 11
  183 +#define PIN_CONFIG_INPUT_SCHMITT 12
  184 +#define PIN_CONFIG_INPUT_DEBOUNCE 13
  185 +#define PIN_CONFIG_POWER_SOURCE 14
  186 +#define PIN_CONFIG_SLEW_RATE 15
  187 +#define PIN_CONFIG_LOW_POWER_MODE 16
  188 +#define PIN_CONFIG_OUTPUT 17
  189 +#define PIN_CONFIG_END 0x7FFF
  190 +
  191 +#if CONFIG_IS_ENABLED(PINCTRL_GENERIC)
  192 +/**
  193 + * pinctrl_generic_set_state() - generic set_state operation
  194 + * Parse the DT node of @config and its children and handle generic properties
  195 + * such as "pins", "groups", "functions", and pin configuration parameters.
  196 + *
  197 + * @pctldev: pinctrl device
  198 + * @config: config device (pseudo device), pointing a config node in DTS
  199 + * @return: 0 on success, or negative error code on failure
  200 + */
  201 +int pinctrl_generic_set_state(struct udevice *pctldev, struct udevice *config);
  202 +#else
  203 +static inline int pinctrl_generic_set_state(struct udevice *pctldev,
  204 + struct udevice *config)
  205 +{
  206 + return -EINVAL;
  207 +}
  208 +#endif
  209 +
  210 +#if CONFIG_IS_ENABLED(PINCTRL)
  211 +/**
  212 + * pinctrl_select_state() - set a device to a given state
  213 + *
  214 + * @dev: peripheral device
  215 + * @statename: state name, like "default"
  216 + * @return: 0 on success, or negative error code on failure
  217 + */
  218 +int pinctrl_select_state(struct udevice *dev, const char *statename);
  219 +#else
  220 +static inline int pinctrl_select_state(struct udevice *dev,
  221 + const char *statename)
  222 +{
  223 + return -EINVAL;
  224 +}
  225 +#endif
  226 +
  227 +#endif /* __PINCTRL_H */
include/dm/uclass-id.h
... ... @@ -44,6 +44,8 @@
44 44 UCLASS_PCH, /* x86 platform controller hub */
45 45 UCLASS_PCI, /* PCI bus */
46 46 UCLASS_PCI_GENERIC, /* Generic PCI bus device */
  47 + UCLASS_PINCTRL, /* Pinctrl (pin muxing/configuration) device */
  48 + UCLASS_PINCONFIG, /* Pin configuration node device */
47 49 UCLASS_PMIC, /* PMIC I/O device */
48 50 UCLASS_REGULATOR, /* Regulator device */
49 51 UCLASS_RESET, /* Reset device */