root/drivers/iio/potentiometer/tpl0102.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tpl0102_read_raw
  2. tpl0102_read_avail
  3. tpl0102_write_raw
  4. tpl0102_probe

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * tpl0102.c - Support for Texas Instruments digital potentiometers
   4  *
   5  * Copyright (C) 2016, 2018
   6  * Author: Matt Ranostay <matt.ranostay@konsulko.com>
   7  *
   8  * TODO: enable/disable hi-z output control
   9  */
  10 
  11 #include <linux/module.h>
  12 #include <linux/i2c.h>
  13 #include <linux/regmap.h>
  14 #include <linux/iio/iio.h>
  15 
  16 struct tpl0102_cfg {
  17         int wipers;
  18         int avail[3];
  19         int kohms;
  20 };
  21 
  22 enum tpl0102_type {
  23         CAT5140_503,
  24         CAT5140_104,
  25         TPL0102_104,
  26         TPL0401_103,
  27 };
  28 
  29 static const struct tpl0102_cfg tpl0102_cfg[] = {
  30         /* on-semiconductor parts */
  31         [CAT5140_503] = { .wipers = 1, .avail = { 0, 1, 255 }, .kohms = 50, },
  32         [CAT5140_104] = { .wipers = 1, .avail = { 0, 1, 255 }, .kohms = 100, },
  33         /* ti parts */
  34         [TPL0102_104] = { .wipers = 2, .avail = { 0, 1, 255 }, .kohms = 100 },
  35         [TPL0401_103] = { .wipers = 1, .avail = { 0, 1, 127 }, .kohms = 10, },
  36 };
  37 
  38 struct tpl0102_data {
  39         struct regmap *regmap;
  40         const struct tpl0102_cfg *cfg;
  41 };
  42 
  43 static const struct regmap_config tpl0102_regmap_config = {
  44         .reg_bits = 8,
  45         .val_bits = 8,
  46 };
  47 
  48 #define TPL0102_CHANNEL(ch) {                                   \
  49         .type = IIO_RESISTANCE,                                 \
  50         .indexed = 1,                                           \
  51         .output = 1,                                            \
  52         .channel = (ch),                                        \
  53         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
  54         .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
  55         .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW), \
  56 }
  57 
  58 static const struct iio_chan_spec tpl0102_channels[] = {
  59         TPL0102_CHANNEL(0),
  60         TPL0102_CHANNEL(1),
  61 };
  62 
  63 static int tpl0102_read_raw(struct iio_dev *indio_dev,
  64                             struct iio_chan_spec const *chan,
  65                             int *val, int *val2, long mask)
  66 {
  67         struct tpl0102_data *data = iio_priv(indio_dev);
  68 
  69         switch (mask) {
  70         case IIO_CHAN_INFO_RAW: {
  71                 int ret = regmap_read(data->regmap, chan->channel, val);
  72 
  73                 return ret ? ret : IIO_VAL_INT;
  74         }
  75         case IIO_CHAN_INFO_SCALE:
  76                 *val = 1000 * data->cfg->kohms;
  77                 *val2 = data->cfg->avail[2] + 1;
  78                 return IIO_VAL_FRACTIONAL;
  79         }
  80 
  81         return -EINVAL;
  82 }
  83 
  84 static int tpl0102_read_avail(struct iio_dev *indio_dev,
  85                               struct iio_chan_spec const *chan,
  86                               const int **vals, int *type, int *length,
  87                               long mask)
  88 {
  89         struct tpl0102_data *data = iio_priv(indio_dev);
  90 
  91         switch (mask) {
  92         case IIO_CHAN_INFO_RAW:
  93                 *length = ARRAY_SIZE(data->cfg->avail);
  94                 *vals = data->cfg->avail;
  95                 *type = IIO_VAL_INT;
  96                 return IIO_AVAIL_RANGE;
  97         }
  98 
  99         return -EINVAL;
 100 }
 101 
 102 static int tpl0102_write_raw(struct iio_dev *indio_dev,
 103                              struct iio_chan_spec const *chan,
 104                              int val, int val2, long mask)
 105 {
 106         struct tpl0102_data *data = iio_priv(indio_dev);
 107 
 108         if (mask != IIO_CHAN_INFO_RAW)
 109                 return -EINVAL;
 110 
 111         if (val > data->cfg->avail[2] || val < 0)
 112                 return -EINVAL;
 113 
 114         return regmap_write(data->regmap, chan->channel, val);
 115 }
 116 
 117 static const struct iio_info tpl0102_info = {
 118         .read_raw = tpl0102_read_raw,
 119         .read_avail = tpl0102_read_avail,
 120         .write_raw = tpl0102_write_raw,
 121 };
 122 
 123 static int tpl0102_probe(struct i2c_client *client,
 124                          const struct i2c_device_id *id)
 125 {
 126         struct device *dev = &client->dev;
 127         struct tpl0102_data *data;
 128         struct iio_dev *indio_dev;
 129 
 130         indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
 131         if (!indio_dev)
 132                 return -ENOMEM;
 133         data = iio_priv(indio_dev);
 134         i2c_set_clientdata(client, indio_dev);
 135 
 136         data->cfg = &tpl0102_cfg[id->driver_data];
 137         data->regmap = devm_regmap_init_i2c(client, &tpl0102_regmap_config);
 138         if (IS_ERR(data->regmap)) {
 139                 dev_err(dev, "regmap initialization failed\n");
 140                 return PTR_ERR(data->regmap);
 141         }
 142 
 143         indio_dev->dev.parent = dev;
 144         indio_dev->info = &tpl0102_info;
 145         indio_dev->channels = tpl0102_channels;
 146         indio_dev->num_channels = data->cfg->wipers;
 147         indio_dev->name = client->name;
 148 
 149         return devm_iio_device_register(dev, indio_dev);
 150 }
 151 
 152 static const struct i2c_device_id tpl0102_id[] = {
 153         { "cat5140-503", CAT5140_503 },
 154         { "cat5140-104", CAT5140_104 },
 155         { "tpl0102-104", TPL0102_104 },
 156         { "tpl0401-103", TPL0401_103 },
 157         {}
 158 };
 159 MODULE_DEVICE_TABLE(i2c, tpl0102_id);
 160 
 161 static struct i2c_driver tpl0102_driver = {
 162         .driver = {
 163                 .name = "tpl0102",
 164         },
 165         .probe = tpl0102_probe,
 166         .id_table = tpl0102_id,
 167 };
 168 
 169 module_i2c_driver(tpl0102_driver);
 170 
 171 MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");
 172 MODULE_DESCRIPTION("TPL0102 digital potentiometer");
 173 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */