uboot/drivers/mux/mux-uclass.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Multiplexer subsystem
   4 *
   5 * Based on the linux multiplexer framework
   6 *
   7 * Copyright (C) 2017 Axentia Technologies AB
   8 * Author: Peter Rosin <peda@axentia.se>
   9 *
  10 * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
  11 * Jean-Jacques Hiblot <jjhiblot@ti.com>
  12 */
  13
  14#include <common.h>
  15#include <dm.h>
  16#include <mux-internal.h>
  17#include <dm/device-internal.h>
  18#include <dm/device_compat.h>
  19#include <dm/devres.h>
  20#include <dt-bindings/mux/mux.h>
  21#include <linux/bug.h>
  22
  23/*
  24 * The idle-as-is "state" is not an actual state that may be selected, it
  25 * only implies that the state should not be changed. So, use that state
  26 * as indication that the cached state of the multiplexer is unknown.
  27 */
  28#define MUX_CACHE_UNKNOWN MUX_IDLE_AS_IS
  29
  30/**
  31 * mux_control_ops() - Get the mux_control ops.
  32 * @dev: The client device.
  33 *
  34 * Return: A pointer to the 'mux_control_ops' of the device.
  35 */
  36static inline const struct mux_control_ops *mux_dev_ops(struct udevice *dev)
  37{
  38        return (const struct mux_control_ops *)dev->driver->ops;
  39}
  40
  41/**
  42 * mux_control_set() - Set the state of the given mux controller.
  43 * @mux: A multiplexer control
  44 * @state: The new requested state.
  45 *
  46 * Return: 0 if OK, or a negative error code.
  47 */
  48static int mux_control_set(struct mux_control *mux, int state)
  49{
  50        int ret = mux_dev_ops(mux->dev)->set(mux, state);
  51
  52        mux->cached_state = ret < 0 ? MUX_CACHE_UNKNOWN : state;
  53
  54        return ret;
  55}
  56
  57unsigned int mux_control_states(struct mux_control *mux)
  58{
  59        return mux->states;
  60}
  61
  62/**
  63 * __mux_control_select() - Select the given multiplexer state.
  64 * @mux: The mux-control to request a change of state from.
  65 * @state: The new requested state.
  66 *
  67 * Try to set the mux to the requested state. If not, try to revert if
  68 * appropriate.
  69 */
  70static int __mux_control_select(struct mux_control *mux, int state)
  71{
  72        int ret;
  73
  74        if (WARN_ON(state < 0 || state >= mux->states))
  75                return -EINVAL;
  76
  77        if (mux->cached_state == state)
  78                return 0;
  79
  80        ret = mux_control_set(mux, state);
  81        if (ret >= 0)
  82                return 0;
  83
  84        /* The mux update failed, try to revert if appropriate... */
  85        if (mux->idle_state != MUX_IDLE_AS_IS)
  86                mux_control_set(mux, mux->idle_state);
  87
  88        return ret;
  89}
  90
  91int mux_control_select(struct mux_control *mux, unsigned int state)
  92{
  93        int ret;
  94
  95        if (mux->in_use)
  96                return -EBUSY;
  97
  98        ret = __mux_control_select(mux, state);
  99
 100        if (ret < 0)
 101                return ret;
 102
 103        mux->in_use = true;
 104
 105        return 0;
 106}
 107
 108int mux_control_deselect(struct mux_control *mux)
 109{
 110        int ret = 0;
 111
 112        if (mux->idle_state != MUX_IDLE_AS_IS &&
 113            mux->idle_state != mux->cached_state)
 114                ret = mux_control_set(mux, mux->idle_state);
 115
 116        mux->in_use = false;
 117
 118        return ret;
 119}
 120
 121static int mux_of_xlate_default(struct mux_chip *mux_chip,
 122                                struct ofnode_phandle_args *args,
 123                                struct mux_control **muxp)
 124{
 125        struct mux_control *mux;
 126        int id;
 127
 128        log_debug("%s(muxp=%p)\n", __func__, muxp);
 129
 130        if (args->args_count > 1) {
 131                debug("Invaild args_count: %d\n", args->args_count);
 132                return -EINVAL;
 133        }
 134
 135        if (args->args_count)
 136                id = args->args[0];
 137        else
 138                id = 0;
 139
 140        if (id >= mux_chip->controllers) {
 141                pr_err("bad mux controller %u specified in %s\n",
 142                        id, ofnode_get_name(args->node));
 143                return -ERANGE;
 144        }
 145
 146        mux = &mux_chip->mux[id];
 147        mux->id = id;
 148        *muxp = mux;
 149        return 0;
 150}
 151
 152/**
 153 * mux_get_by_indexed_prop() - Get a mux control by integer index
 154 * @dev: The client device.
 155 * @prop_name: Name of the device tree property.
 156 * @index: The index of the mux to get
 157 * @mux: A pointer to the 'mux_control' struct to initialize.
 158 *
 159 * Return: 0 of OK, -errno otherwise.
 160 */
 161static int mux_get_by_indexed_prop(struct udevice *dev, const char *prop_name,
 162                                   int index, struct mux_control **mux)
 163{
 164        int ret;
 165        struct ofnode_phandle_args args;
 166        struct udevice *dev_mux;
 167        const struct mux_control_ops *ops;
 168        struct mux_chip *mux_chip;
 169
 170        log_debug("%s(dev=%p, index=%d, mux=%p)\n", __func__, dev, index, mux);
 171
 172        ret = dev_read_phandle_with_args(dev, prop_name, "#mux-control-cells",
 173                                         0, index, &args);
 174        if (ret) {
 175                debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
 176                      __func__, ret);
 177                return ret;
 178        }
 179
 180        ret = uclass_get_device_by_ofnode(UCLASS_MUX, args.node, &dev_mux);
 181        if (ret) {
 182                debug("%s: uclass_get_device_by_ofnode failed: err=%d\n",
 183                      __func__, ret);
 184                return ret;
 185        }
 186
 187        mux_chip = dev_get_uclass_priv(dev_mux);
 188
 189        ops = mux_dev_ops(dev_mux);
 190        if (ops->of_xlate)
 191                ret = ops->of_xlate(mux_chip, &args, mux);
 192        else
 193                ret = mux_of_xlate_default(mux_chip, &args, mux);
 194        if (ret) {
 195                debug("of_xlate() failed: %d\n", ret);
 196                return ret;
 197        }
 198        (*mux)->dev = dev_mux;
 199
 200        return 0;
 201}
 202
 203int mux_get_by_index(struct udevice *dev, int index, struct mux_control **mux)
 204{
 205        return mux_get_by_indexed_prop(dev, "mux-controls", index, mux);
 206}
 207
 208int mux_control_get(struct udevice *dev, const char *name,
 209                    struct mux_control **mux)
 210{
 211        int index;
 212
 213        debug("%s(dev=%p, name=%s, mux=%p)\n", __func__, dev, name, mux);
 214
 215        index = dev_read_stringlist_search(dev, "mux-control-names", name);
 216        if (index < 0) {
 217                debug("fdt_stringlist_search() failed: %d\n", index);
 218                return index;
 219        }
 220
 221        return mux_get_by_index(dev, index, mux);
 222}
 223
 224void mux_control_put(struct mux_control *mux)
 225{
 226        mux_control_deselect(mux);
 227}
 228
 229/**
 230 * devm_mux_control_release() - Release the given managed mux.
 231 * @dev: The client device.
 232 * @res: Pointer to the mux to be released.
 233 *
 234 * This function is called by devres to release the mux. It reverses the
 235 * effects of mux_control_get().
 236 */
 237static void devm_mux_control_release(struct udevice *dev, void *res)
 238{
 239        mux_control_put(*(struct mux_control **)res);
 240}
 241
 242struct mux_control *devm_mux_control_get(struct udevice *dev, const char *id)
 243{
 244        int rc;
 245        struct mux_control **mux;
 246
 247        mux = devres_alloc(devm_mux_control_release,
 248                           sizeof(struct mux_control *), __GFP_ZERO);
 249        if (unlikely(!mux))
 250                return ERR_PTR(-ENOMEM);
 251
 252        rc = mux_control_get(dev, id, mux);
 253        if (rc)
 254                return ERR_PTR(rc);
 255
 256        devres_add(dev, mux);
 257        return *mux;
 258}
 259
 260int mux_alloc_controllers(struct udevice *dev, unsigned int controllers)
 261{
 262        int i;
 263        struct mux_chip *mux_chip = dev_get_uclass_priv(dev);
 264
 265        mux_chip->mux = devm_kmalloc(dev,
 266                                     sizeof(struct mux_control) * controllers,
 267                                     __GFP_ZERO);
 268        if (!mux_chip->mux)
 269                return -ENOMEM;
 270
 271        mux_chip->controllers = controllers;
 272
 273        for (i = 0; i < mux_chip->controllers; ++i) {
 274                struct mux_control *mux = &mux_chip->mux[i];
 275
 276                mux->dev = dev;
 277                mux->cached_state = MUX_CACHE_UNKNOWN;
 278                mux->idle_state = MUX_IDLE_AS_IS;
 279                mux->in_use = false;
 280                mux->id = i;
 281        }
 282
 283        return 0;
 284}
 285
 286static int mux_uclass_post_probe(struct udevice *dev)
 287{
 288        int i, ret;
 289        struct mux_chip *mux_chip = dev_get_uclass_priv(dev);
 290
 291        /* Set all mux controllers to their idle state. */
 292        for (i = 0; i < mux_chip->controllers; ++i) {
 293                struct mux_control *mux = &mux_chip->mux[i];
 294
 295                if (mux->idle_state == mux->cached_state)
 296                        continue;
 297
 298                ret = mux_control_set(mux, mux->idle_state);
 299                if (ret < 0) {
 300                        dev_err(dev, "unable to set idle state\n");
 301                        return ret;
 302                }
 303        }
 304        return 0;
 305}
 306
 307int dm_mux_init(void)
 308{
 309        struct uclass *uc;
 310        struct udevice *dev;
 311        int ret;
 312
 313        ret = uclass_get(UCLASS_MUX, &uc);
 314        if (ret < 0) {
 315                log_debug("unable to get MUX uclass\n");
 316                return ret;
 317        }
 318        uclass_foreach_dev(dev, uc) {
 319                if (dev_read_bool(dev, "u-boot,mux-autoprobe")) {
 320                        ret = device_probe(dev);
 321                        if (ret)
 322                                log_debug("unable to probe device %s\n",
 323                                          dev->name);
 324                }
 325        }
 326
 327        return 0;
 328}
 329
 330UCLASS_DRIVER(mux) = {
 331        .id             = UCLASS_MUX,
 332        .name           = "mux",
 333        .post_probe     = mux_uclass_post_probe,
 334        .per_device_auto_alloc_size = sizeof(struct mux_chip),
 335};
 336