linux/drivers/mux/mmio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * MMIO register bitfield-controlled multiplexer driver
   4 *
   5 * Copyright (C) 2017 Pengutronix, Philipp Zabel <kernel@pengutronix.de>
   6 */
   7
   8#include <linux/bitops.h>
   9#include <linux/err.h>
  10#include <linux/mfd/syscon.h>
  11#include <linux/module.h>
  12#include <linux/mux/driver.h>
  13#include <linux/of_platform.h>
  14#include <linux/platform_device.h>
  15#include <linux/property.h>
  16#include <linux/regmap.h>
  17
  18static int mux_mmio_set(struct mux_control *mux, int state)
  19{
  20        struct regmap_field **fields = mux_chip_priv(mux->chip);
  21
  22        return regmap_field_write(fields[mux_control_get_index(mux)], state);
  23}
  24
  25static const struct mux_control_ops mux_mmio_ops = {
  26        .set = mux_mmio_set,
  27};
  28
  29static const struct of_device_id mux_mmio_dt_ids[] = {
  30        { .compatible = "mmio-mux", },
  31        { .compatible = "reg-mux", },
  32        { /* sentinel */ }
  33};
  34MODULE_DEVICE_TABLE(of, mux_mmio_dt_ids);
  35
  36static int mux_mmio_probe(struct platform_device *pdev)
  37{
  38        struct device *dev = &pdev->dev;
  39        struct device_node *np = dev->of_node;
  40        struct regmap_field **fields;
  41        struct mux_chip *mux_chip;
  42        struct regmap *regmap;
  43        int num_fields;
  44        int ret;
  45        int i;
  46
  47        if (of_device_is_compatible(np, "mmio-mux"))
  48                regmap = syscon_node_to_regmap(np->parent);
  49        else
  50                regmap = dev_get_regmap(dev->parent, NULL) ?: ERR_PTR(-ENODEV);
  51        if (IS_ERR(regmap)) {
  52                ret = PTR_ERR(regmap);
  53                dev_err(dev, "failed to get regmap: %d\n", ret);
  54                return ret;
  55        }
  56
  57        ret = of_property_count_u32_elems(np, "mux-reg-masks");
  58        if (ret == 0 || ret % 2)
  59                ret = -EINVAL;
  60        if (ret < 0) {
  61                dev_err(dev, "mux-reg-masks property missing or invalid: %d\n",
  62                        ret);
  63                return ret;
  64        }
  65        num_fields = ret / 2;
  66
  67        mux_chip = devm_mux_chip_alloc(dev, num_fields, num_fields *
  68                                       sizeof(*fields));
  69        if (IS_ERR(mux_chip))
  70                return PTR_ERR(mux_chip);
  71
  72        fields = mux_chip_priv(mux_chip);
  73
  74        for (i = 0; i < num_fields; i++) {
  75                struct mux_control *mux = &mux_chip->mux[i];
  76                struct reg_field field;
  77                s32 idle_state = MUX_IDLE_AS_IS;
  78                u32 reg, mask;
  79                int bits;
  80
  81                ret = of_property_read_u32_index(np, "mux-reg-masks",
  82                                                 2 * i, &reg);
  83                if (!ret)
  84                        ret = of_property_read_u32_index(np, "mux-reg-masks",
  85                                                         2 * i + 1, &mask);
  86                if (ret < 0) {
  87                        dev_err(dev, "bitfield %d: failed to read mux-reg-masks property: %d\n",
  88                                i, ret);
  89                        return ret;
  90                }
  91
  92                field.reg = reg;
  93                field.msb = fls(mask) - 1;
  94                field.lsb = ffs(mask) - 1;
  95
  96                if (mask != GENMASK(field.msb, field.lsb)) {
  97                        dev_err(dev, "bitfield %d: invalid mask 0x%x\n",
  98                                i, mask);
  99                        return -EINVAL;
 100                }
 101
 102                fields[i] = devm_regmap_field_alloc(dev, regmap, field);
 103                if (IS_ERR(fields[i])) {
 104                        ret = PTR_ERR(fields[i]);
 105                        dev_err(dev, "bitfield %d: failed allocate: %d\n",
 106                                i, ret);
 107                        return ret;
 108                }
 109
 110                bits = 1 + field.msb - field.lsb;
 111                mux->states = 1 << bits;
 112
 113                of_property_read_u32_index(np, "idle-states", i,
 114                                           (u32 *)&idle_state);
 115                if (idle_state != MUX_IDLE_AS_IS) {
 116                        if (idle_state < 0 || idle_state >= mux->states) {
 117                                dev_err(dev, "bitfield: %d: out of range idle state %d\n",
 118                                        i, idle_state);
 119                                return -EINVAL;
 120                        }
 121
 122                        mux->idle_state = idle_state;
 123                }
 124        }
 125
 126        mux_chip->ops = &mux_mmio_ops;
 127
 128        return devm_mux_chip_register(dev, mux_chip);
 129}
 130
 131static struct platform_driver mux_mmio_driver = {
 132        .driver = {
 133                .name = "mmio-mux",
 134                .of_match_table = of_match_ptr(mux_mmio_dt_ids),
 135        },
 136        .probe = mux_mmio_probe,
 137};
 138module_platform_driver(mux_mmio_driver);
 139
 140MODULE_DESCRIPTION("MMIO register bitfield-controlled multiplexer driver");
 141MODULE_AUTHOR("Philipp Zabel <p.zabel@pengutronix.de>");
 142MODULE_LICENSE("GPL v2");
 143