uboot/drivers/mux/mmio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * MMIO register bitfield-controlled multiplexer driver
   4 * Based on the linux mmio multiplexer driver
   5 *
   6 * Copyright (C) 2017 Pengutronix, Philipp Zabel <kernel@pengutronix.de>
   7 * Copyright (C) 2019 Texas Instrument, Jean-jacques Hiblot <jjhiblot@ti.com>
   8 */
   9#include <common.h>
  10#include <dm.h>
  11#include <mux-internal.h>
  12#include <regmap.h>
  13#include <syscon.h>
  14#include <dm/device.h>
  15#include <dm/device-internal.h>
  16#include <dm/device_compat.h>
  17#include <dm/read.h>
  18#include <dm/devres.h>
  19#include <dt-bindings/mux/mux.h>
  20#include <linux/bitops.h>
  21
  22static int mux_mmio_set(struct mux_control *mux, int state)
  23{
  24        struct regmap_field **fields = dev_get_priv(mux->dev);
  25
  26        return regmap_field_write(fields[mux_control_get_index(mux)], state);
  27}
  28
  29static const struct mux_control_ops mux_mmio_ops = {
  30        .set = mux_mmio_set,
  31};
  32
  33static const struct udevice_id mmio_mux_of_match[] = {
  34        { .compatible = "mmio-mux" },
  35        { /* sentinel */ },
  36};
  37
  38static int mmio_mux_probe(struct udevice *dev)
  39{
  40        struct regmap_field **fields;
  41        struct mux_chip *mux_chip = dev_get_uclass_priv(dev);
  42        struct regmap *regmap;
  43        u32 *mux_reg_masks;
  44        u32 *idle_states;
  45        int num_fields;
  46        int ret;
  47        int i;
  48
  49        regmap = syscon_node_to_regmap(dev_ofnode(dev->parent));
  50        if (IS_ERR(regmap)) {
  51                ret = PTR_ERR(regmap);
  52                dev_err(dev, "failed to get regmap: %d\n", ret);
  53                return ret;
  54        }
  55
  56        num_fields = dev_read_size(dev, "mux-reg-masks");
  57        if (num_fields < 0)
  58                return log_msg_ret("mux-reg-masks missing", -EINVAL);
  59
  60        num_fields /= sizeof(u32);
  61        if (num_fields == 0 || num_fields % 2)
  62                ret = -EINVAL;
  63        num_fields = num_fields / 2;
  64
  65        ret = mux_alloc_controllers(dev, num_fields);
  66        if (ret < 0)
  67                return log_msg_ret("mux_alloc_controllers", ret);
  68
  69        fields = devm_kmalloc(dev, num_fields * sizeof(*fields), __GFP_ZERO);
  70        if (!fields)
  71                return -ENOMEM;
  72        dev_set_priv(dev, fields);
  73
  74        mux_reg_masks = devm_kmalloc(dev, num_fields * 2 * sizeof(u32),
  75                                     __GFP_ZERO);
  76        if (!mux_reg_masks)
  77                return -ENOMEM;
  78
  79        ret = dev_read_u32_array(dev, "mux-reg-masks", mux_reg_masks,
  80                                 num_fields * 2);
  81        if (ret < 0)
  82                return log_msg_ret("mux-reg-masks read", ret);
  83
  84        idle_states = devm_kmalloc(dev, num_fields * sizeof(u32), __GFP_ZERO);
  85        if (!idle_states)
  86                return -ENOMEM;
  87
  88        ret = dev_read_u32_array(dev, "idle-states", idle_states, num_fields);
  89        if (ret < 0) {
  90                log_err("idle-states");
  91                devm_kfree(dev, idle_states);
  92                idle_states = NULL;
  93        }
  94
  95        for (i = 0; i < num_fields; i++) {
  96                struct mux_control *mux = &mux_chip->mux[i];
  97                struct reg_field field;
  98                u32 reg, mask;
  99                int bits;
 100
 101                reg = mux_reg_masks[2 * i];
 102                mask = mux_reg_masks[2 * i + 1];
 103
 104                field.reg = reg;
 105                field.msb = fls(mask) - 1;
 106                field.lsb = ffs(mask) - 1;
 107
 108                if (mask != GENMASK(field.msb, field.lsb))
 109                        return log_msg_ret("invalid mask", -EINVAL);
 110
 111                fields[i] = devm_regmap_field_alloc(dev, regmap, field);
 112                if (IS_ERR(fields[i])) {
 113                        ret = PTR_ERR(fields[i]);
 114                        return log_msg_ret("regmap_field_alloc", ret);
 115                }
 116
 117                bits = 1 + field.msb - field.lsb;
 118                mux->states = 1 << bits;
 119
 120                if (!idle_states)
 121                        continue;
 122
 123                if (idle_states[i] != MUX_IDLE_AS_IS &&
 124                    idle_states[i] >= mux->states)
 125                        return log_msg_ret("idle-states range", -EINVAL);
 126
 127                mux->idle_state = idle_states[i];
 128        }
 129
 130        devm_kfree(dev, mux_reg_masks);
 131        if (idle_states)
 132                devm_kfree(dev, idle_states);
 133
 134        return 0;
 135}
 136
 137U_BOOT_DRIVER(mmio_mux) = {
 138        .name = "mmio-mux",
 139        .id = UCLASS_MUX,
 140        .of_match = mmio_mux_of_match,
 141        .probe = mmio_mux_probe,
 142        .ops = &mux_mmio_ops,
 143};
 144