linux/drivers/iio/dac/ds4424.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Maxim Integrated
   4 * 7-bit, Multi-Channel Sink/Source Current DAC Driver
   5 * Copyright (C) 2017 Maxim Integrated
   6 */
   7
   8#include <linux/kernel.h>
   9#include <linux/module.h>
  10#include <linux/i2c.h>
  11#include <linux/regulator/consumer.h>
  12#include <linux/err.h>
  13#include <linux/delay.h>
  14#include <linux/iio/iio.h>
  15#include <linux/iio/driver.h>
  16#include <linux/iio/machine.h>
  17#include <linux/iio/consumer.h>
  18
  19#define DS4422_MAX_DAC_CHANNELS         2
  20#define DS4424_MAX_DAC_CHANNELS         4
  21
  22#define DS4424_DAC_ADDR(chan)   ((chan) + 0xf8)
  23#define DS4424_SOURCE_I         1
  24#define DS4424_SINK_I           0
  25
  26#define DS4424_CHANNEL(chan) { \
  27        .type = IIO_CURRENT, \
  28        .indexed = 1, \
  29        .output = 1, \
  30        .channel = chan, \
  31        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
  32}
  33
  34/*
  35 * DS4424 DAC control register 8 bits
  36 * [7]          0: to sink; 1: to source
  37 * [6:0]        steps to sink/source
  38 * bit[7] looks like a sign bit, but the value of the register is
  39 * not a two's complement code considering the bit[6:0] is a absolute
  40 * distance from the zero point.
  41 */
  42union ds4424_raw_data {
  43        struct {
  44                u8 dx:7;
  45                u8 source_bit:1;
  46        };
  47        u8 bits;
  48};
  49
  50enum ds4424_device_ids {
  51        ID_DS4422,
  52        ID_DS4424,
  53};
  54
  55struct ds4424_data {
  56        struct i2c_client *client;
  57        struct mutex lock;
  58        uint8_t save[DS4424_MAX_DAC_CHANNELS];
  59        struct regulator *vcc_reg;
  60        uint8_t raw[DS4424_MAX_DAC_CHANNELS];
  61};
  62
  63static const struct iio_chan_spec ds4424_channels[] = {
  64        DS4424_CHANNEL(0),
  65        DS4424_CHANNEL(1),
  66        DS4424_CHANNEL(2),
  67        DS4424_CHANNEL(3),
  68};
  69
  70static int ds4424_get_value(struct iio_dev *indio_dev,
  71                             int *val, int channel)
  72{
  73        struct ds4424_data *data = iio_priv(indio_dev);
  74        int ret;
  75
  76        mutex_lock(&data->lock);
  77        ret = i2c_smbus_read_byte_data(data->client, DS4424_DAC_ADDR(channel));
  78        if (ret < 0)
  79                goto fail;
  80
  81        *val = ret;
  82
  83fail:
  84        mutex_unlock(&data->lock);
  85        return ret;
  86}
  87
  88static int ds4424_set_value(struct iio_dev *indio_dev,
  89                             int val, struct iio_chan_spec const *chan)
  90{
  91        struct ds4424_data *data = iio_priv(indio_dev);
  92        int ret;
  93
  94        mutex_lock(&data->lock);
  95        ret = i2c_smbus_write_byte_data(data->client,
  96                        DS4424_DAC_ADDR(chan->channel), val);
  97        if (ret < 0)
  98                goto fail;
  99
 100        data->raw[chan->channel] = val;
 101
 102fail:
 103        mutex_unlock(&data->lock);
 104        return ret;
 105}
 106
 107static int ds4424_read_raw(struct iio_dev *indio_dev,
 108                           struct iio_chan_spec const *chan,
 109                           int *val, int *val2, long mask)
 110{
 111        union ds4424_raw_data raw;
 112        int ret;
 113
 114        switch (mask) {
 115        case IIO_CHAN_INFO_RAW:
 116                ret = ds4424_get_value(indio_dev, val, chan->channel);
 117                if (ret < 0) {
 118                        pr_err("%s : ds4424_get_value returned %d\n",
 119                                                        __func__, ret);
 120                        return ret;
 121                }
 122                raw.bits = *val;
 123                *val = raw.dx;
 124                if (raw.source_bit == DS4424_SINK_I)
 125                        *val = -*val;
 126                return IIO_VAL_INT;
 127
 128        default:
 129                return -EINVAL;
 130        }
 131}
 132
 133static int ds4424_write_raw(struct iio_dev *indio_dev,
 134                             struct iio_chan_spec const *chan,
 135                             int val, int val2, long mask)
 136{
 137        union ds4424_raw_data raw;
 138
 139        if (val2 != 0)
 140                return -EINVAL;
 141
 142        switch (mask) {
 143        case IIO_CHAN_INFO_RAW:
 144                if (val < S8_MIN || val > S8_MAX)
 145                        return -EINVAL;
 146
 147                if (val > 0) {
 148                        raw.source_bit = DS4424_SOURCE_I;
 149                        raw.dx = val;
 150                } else {
 151                        raw.source_bit = DS4424_SINK_I;
 152                        raw.dx = -val;
 153                }
 154
 155                return ds4424_set_value(indio_dev, raw.bits, chan);
 156
 157        default:
 158                return -EINVAL;
 159        }
 160}
 161
 162static int ds4424_verify_chip(struct iio_dev *indio_dev)
 163{
 164        int ret, val;
 165
 166        ret = ds4424_get_value(indio_dev, &val, 0);
 167        if (ret < 0)
 168                dev_err(&indio_dev->dev,
 169                                "%s failed. ret: %d\n", __func__, ret);
 170
 171        return ret;
 172}
 173
 174static int __maybe_unused ds4424_suspend(struct device *dev)
 175{
 176        struct i2c_client *client = to_i2c_client(dev);
 177        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 178        struct ds4424_data *data = iio_priv(indio_dev);
 179        int ret = 0;
 180        int i;
 181
 182        for (i = 0; i < indio_dev->num_channels; i++) {
 183                data->save[i] = data->raw[i];
 184                ret = ds4424_set_value(indio_dev, 0,
 185                                &indio_dev->channels[i]);
 186                if (ret < 0)
 187                        return ret;
 188        }
 189        return ret;
 190}
 191
 192static int __maybe_unused ds4424_resume(struct device *dev)
 193{
 194        struct i2c_client *client = to_i2c_client(dev);
 195        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 196        struct ds4424_data *data = iio_priv(indio_dev);
 197        int ret = 0;
 198        int i;
 199
 200        for (i = 0; i < indio_dev->num_channels; i++) {
 201                ret = ds4424_set_value(indio_dev, data->save[i],
 202                                &indio_dev->channels[i]);
 203                if (ret < 0)
 204                        return ret;
 205        }
 206        return ret;
 207}
 208
 209static SIMPLE_DEV_PM_OPS(ds4424_pm_ops, ds4424_suspend, ds4424_resume);
 210
 211static const struct iio_info ds4424_info = {
 212        .read_raw = ds4424_read_raw,
 213        .write_raw = ds4424_write_raw,
 214};
 215
 216static int ds4424_probe(struct i2c_client *client,
 217                        const struct i2c_device_id *id)
 218{
 219        struct ds4424_data *data;
 220        struct iio_dev *indio_dev;
 221        int ret;
 222
 223        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 224        if (!indio_dev) {
 225                dev_err(&client->dev, "iio dev alloc failed.\n");
 226                return -ENOMEM;
 227        }
 228
 229        data = iio_priv(indio_dev);
 230        i2c_set_clientdata(client, indio_dev);
 231        data->client = client;
 232        indio_dev->name = id->name;
 233
 234        data->vcc_reg = devm_regulator_get(&client->dev, "vcc");
 235        if (IS_ERR(data->vcc_reg)) {
 236                dev_err(&client->dev,
 237                        "Failed to get vcc-supply regulator. err: %ld\n",
 238                                PTR_ERR(data->vcc_reg));
 239                return PTR_ERR(data->vcc_reg);
 240        }
 241
 242        mutex_init(&data->lock);
 243        ret = regulator_enable(data->vcc_reg);
 244        if (ret < 0) {
 245                dev_err(&client->dev,
 246                                "Unable to enable the regulator.\n");
 247                return ret;
 248        }
 249
 250        usleep_range(1000, 1200);
 251        ret = ds4424_verify_chip(indio_dev);
 252        if (ret < 0)
 253                goto fail;
 254
 255        switch (id->driver_data) {
 256        case ID_DS4422:
 257                indio_dev->num_channels = DS4422_MAX_DAC_CHANNELS;
 258                break;
 259        case ID_DS4424:
 260                indio_dev->num_channels = DS4424_MAX_DAC_CHANNELS;
 261                break;
 262        default:
 263                dev_err(&client->dev,
 264                                "ds4424: Invalid chip id.\n");
 265                ret = -ENXIO;
 266                goto fail;
 267        }
 268
 269        indio_dev->channels = ds4424_channels;
 270        indio_dev->modes = INDIO_DIRECT_MODE;
 271        indio_dev->info = &ds4424_info;
 272
 273        ret = iio_device_register(indio_dev);
 274        if (ret < 0) {
 275                dev_err(&client->dev,
 276                                "iio_device_register failed. ret: %d\n", ret);
 277                goto fail;
 278        }
 279
 280        return ret;
 281
 282fail:
 283        regulator_disable(data->vcc_reg);
 284        return ret;
 285}
 286
 287static int ds4424_remove(struct i2c_client *client)
 288{
 289        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 290        struct ds4424_data *data = iio_priv(indio_dev);
 291
 292        iio_device_unregister(indio_dev);
 293        regulator_disable(data->vcc_reg);
 294
 295        return 0;
 296}
 297
 298static const struct i2c_device_id ds4424_id[] = {
 299        { "ds4422", ID_DS4422 },
 300        { "ds4424", ID_DS4424 },
 301        { }
 302};
 303
 304MODULE_DEVICE_TABLE(i2c, ds4424_id);
 305
 306static const struct of_device_id ds4424_of_match[] = {
 307        { .compatible = "maxim,ds4422" },
 308        { .compatible = "maxim,ds4424" },
 309        { },
 310};
 311
 312MODULE_DEVICE_TABLE(of, ds4424_of_match);
 313
 314static struct i2c_driver ds4424_driver = {
 315        .driver = {
 316                .name   = "ds4424",
 317                .of_match_table = ds4424_of_match,
 318                .pm     = &ds4424_pm_ops,
 319        },
 320        .probe          = ds4424_probe,
 321        .remove         = ds4424_remove,
 322        .id_table       = ds4424_id,
 323};
 324module_i2c_driver(ds4424_driver);
 325
 326MODULE_DESCRIPTION("Maxim DS4424 DAC Driver");
 327MODULE_AUTHOR("Ismail H. Kose <ismail.kose@maximintegrated.com>");
 328MODULE_AUTHOR("Vishal Sood <vishal.sood@maximintegrated.com>");
 329MODULE_AUTHOR("David Jung <david.jung@maximintegrated.com>");
 330MODULE_LICENSE("GPL v2");
 331