uboot/drivers/pinctrl/pinctrl-uclass.c
<<
>>
Prefs
   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.h>
  12#include <dm/lists.h>
  13#include <dm/pinctrl.h>
  14#include <dm/util.h>
  15
  16DECLARE_GLOBAL_DATA_PTR;
  17
  18int pinctrl_decode_pin_config(const void *blob, int node)
  19{
  20        int flags = 0;
  21
  22        if (fdtdec_get_bool(blob, node, "bias-pull-up"))
  23                flags |= 1 << PIN_CONFIG_BIAS_PULL_UP;
  24        else if (fdtdec_get_bool(blob, node, "bias-pull-down"))
  25                flags |= 1 << PIN_CONFIG_BIAS_PULL_DOWN;
  26
  27        return flags;
  28}
  29
  30#if CONFIG_IS_ENABLED(PINCTRL_FULL)
  31/**
  32 * pinctrl_config_one() - apply pinctrl settings for a single node
  33 *
  34 * @config: pin configuration node
  35 * @return: 0 on success, or negative error code on failure
  36 */
  37static int pinctrl_config_one(struct udevice *config)
  38{
  39        struct udevice *pctldev;
  40        const struct pinctrl_ops *ops;
  41
  42        pctldev = config;
  43        for (;;) {
  44                pctldev = dev_get_parent(pctldev);
  45                if (!pctldev) {
  46                        dev_err(config, "could not find pctldev\n");
  47                        return -EINVAL;
  48                }
  49                if (pctldev->uclass->uc_drv->id == UCLASS_PINCTRL)
  50                        break;
  51        }
  52
  53        ops = pinctrl_get_ops(pctldev);
  54        return ops->set_state(pctldev, config);
  55}
  56
  57/**
  58 * pinctrl_select_state_full() - full implementation of pinctrl_select_state
  59 *
  60 * @dev: peripheral device
  61 * @statename: state name, like "default"
  62 * @return: 0 on success, or negative error code on failure
  63 */
  64static int pinctrl_select_state_full(struct udevice *dev, const char *statename)
  65{
  66        const void *fdt = gd->fdt_blob;
  67        int node = dev_of_offset(dev);
  68        char propname[32]; /* long enough */
  69        const fdt32_t *list;
  70        uint32_t phandle;
  71        int config_node;
  72        struct udevice *config;
  73        int state, size, i, ret;
  74
  75        state = fdt_stringlist_search(fdt, node, "pinctrl-names", statename);
  76        if (state < 0) {
  77                char *end;
  78                /*
  79                 * If statename is not found in "pinctrl-names",
  80                 * assume statename is just the integer state ID.
  81                 */
  82                state = simple_strtoul(statename, &end, 10);
  83                if (*end)
  84                        return -EINVAL;
  85        }
  86
  87        snprintf(propname, sizeof(propname), "pinctrl-%d", state);
  88        list = fdt_getprop(fdt, node, propname, &size);
  89        if (!list)
  90                return -EINVAL;
  91
  92        size /= sizeof(*list);
  93        for (i = 0; i < size; i++) {
  94                phandle = fdt32_to_cpu(*list++);
  95
  96                config_node = fdt_node_offset_by_phandle(fdt, phandle);
  97                if (config_node < 0) {
  98                        dev_err(dev, "prop %s index %d invalid phandle\n",
  99                                propname, i);
 100                        return -EINVAL;
 101                }
 102                ret = uclass_get_device_by_of_offset(UCLASS_PINCONFIG,
 103                                                     config_node, &config);
 104                if (ret)
 105                        return ret;
 106
 107                ret = pinctrl_config_one(config);
 108                if (ret)
 109                        return ret;
 110        }
 111
 112        return 0;
 113}
 114
 115/**
 116 * pinconfig_post_bind() - post binding for PINCONFIG uclass
 117 * Recursively bind its children as pinconfig devices.
 118 *
 119 * @dev: pinconfig device
 120 * @return: 0 on success, or negative error code on failure
 121 */
 122static int pinconfig_post_bind(struct udevice *dev)
 123{
 124        bool pre_reloc_only = !(gd->flags & GD_FLG_RELOC);
 125        const char *name;
 126        ofnode node;
 127        int ret;
 128
 129        dev_for_each_subnode(node, dev) {
 130                if (pre_reloc_only &&
 131                    !ofnode_pre_reloc(node))
 132                        continue;
 133                /*
 134                 * If this node has "compatible" property, this is not
 135                 * a pin configuration node, but a normal device. skip.
 136                 */
 137                ofnode_get_property(node, "compatible", &ret);
 138                if (ret >= 0)
 139                        continue;
 140
 141                if (ret != -FDT_ERR_NOTFOUND)
 142                        return ret;
 143
 144                name = ofnode_get_name(node);
 145                if (!name)
 146                        return -EINVAL;
 147                ret = device_bind_driver_to_node(dev, "pinconfig", name,
 148                                                 node, NULL);
 149                if (ret)
 150                        return ret;
 151        }
 152
 153        return 0;
 154}
 155
 156UCLASS_DRIVER(pinconfig) = {
 157        .id = UCLASS_PINCONFIG,
 158        .post_bind = pinconfig_post_bind,
 159        .name = "pinconfig",
 160};
 161
 162U_BOOT_DRIVER(pinconfig_generic) = {
 163        .name = "pinconfig",
 164        .id = UCLASS_PINCONFIG,
 165};
 166
 167#else
 168static int pinctrl_select_state_full(struct udevice *dev, const char *statename)
 169{
 170        return -ENODEV;
 171}
 172
 173static int pinconfig_post_bind(struct udevice *dev)
 174{
 175        return 0;
 176}
 177#endif
 178
 179/**
 180 * pinctrl_select_state_simple() - simple implementation of pinctrl_select_state
 181 *
 182 * @dev: peripheral device
 183 * @return: 0 on success, or negative error code on failure
 184 */
 185static int pinctrl_select_state_simple(struct udevice *dev)
 186{
 187        struct udevice *pctldev;
 188        struct pinctrl_ops *ops;
 189        int ret;
 190
 191        /*
 192         * For simplicity, assume the first device of PINCTRL uclass
 193         * is the correct one.  This is most likely OK as there is
 194         * usually only one pinctrl device on the system.
 195         */
 196        ret = uclass_get_device(UCLASS_PINCTRL, 0, &pctldev);
 197        if (ret)
 198                return ret;
 199
 200        ops = pinctrl_get_ops(pctldev);
 201        if (!ops->set_state_simple) {
 202                dev_dbg(dev, "set_state_simple op missing\n");
 203                return -ENOSYS;
 204        }
 205
 206        return ops->set_state_simple(pctldev, dev);
 207}
 208
 209int pinctrl_select_state(struct udevice *dev, const char *statename)
 210{
 211        /*
 212         * Try full-implemented pinctrl first.
 213         * If it fails or is not implemented, try simple one.
 214         */
 215        if (pinctrl_select_state_full(dev, statename))
 216                return pinctrl_select_state_simple(dev);
 217
 218        return 0;
 219}
 220
 221int pinctrl_request(struct udevice *dev, int func, int flags)
 222{
 223        struct pinctrl_ops *ops = pinctrl_get_ops(dev);
 224
 225        if (!ops->request)
 226                return -ENOSYS;
 227
 228        return ops->request(dev, func, flags);
 229}
 230
 231int pinctrl_request_noflags(struct udevice *dev, int func)
 232{
 233        return pinctrl_request(dev, func, 0);
 234}
 235
 236int pinctrl_get_periph_id(struct udevice *dev, struct udevice *periph)
 237{
 238        struct pinctrl_ops *ops = pinctrl_get_ops(dev);
 239
 240        if (!ops->get_periph_id)
 241                return -ENOSYS;
 242
 243        return ops->get_periph_id(dev, periph);
 244}
 245
 246int pinctrl_get_gpio_mux(struct udevice *dev, int banknum, int index)
 247{
 248        struct pinctrl_ops *ops = pinctrl_get_ops(dev);
 249
 250        if (!ops->get_gpio_mux)
 251                return -ENOSYS;
 252
 253        return ops->get_gpio_mux(dev, banknum, index);
 254}
 255
 256/**
 257 * pinconfig_post_bind() - post binding for PINCTRL uclass
 258 * Recursively bind child nodes as pinconfig devices in case of full pinctrl.
 259 *
 260 * @dev: pinctrl device
 261 * @return: 0 on success, or negative error code on failure
 262 */
 263static int pinctrl_post_bind(struct udevice *dev)
 264{
 265        const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
 266
 267        if (!ops) {
 268                dev_dbg(dev, "ops is not set.  Do not bind.\n");
 269                return -EINVAL;
 270        }
 271
 272        /*
 273         * If set_state callback is set, we assume this pinctrl driver is the
 274         * full implementation.  In this case, its child nodes should be bound
 275         * so that peripheral devices can easily search in parent devices
 276         * during later DT-parsing.
 277         */
 278        if (ops->set_state)
 279                return pinconfig_post_bind(dev);
 280
 281        return 0;
 282}
 283
 284UCLASS_DRIVER(pinctrl) = {
 285        .id = UCLASS_PINCTRL,
 286        .post_bind = pinctrl_post_bind,
 287        .flags = DM_UC_FLAG_SEQ_ALIAS,
 288        .name = "pinctrl",
 289};
 290