1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2df38a4a7SSean Nyekjaer /* 3df38a4a7SSean Nyekjaer * ti-dac5571.c - Texas Instruments 8/10/12-bit 1/4-channel DAC driver 4df38a4a7SSean Nyekjaer * 5df38a4a7SSean Nyekjaer * Copyright (C) 2018 Prevas A/S 6df38a4a7SSean Nyekjaer * 73593cd53SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/dac5571.pdf 83593cd53SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/dac6571.pdf 93593cd53SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/dac7571.pdf 103593cd53SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/dac5574.pdf 113593cd53SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/dac6574.pdf 123593cd53SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/dac7574.pdf 133593cd53SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/dac5573.pdf 143593cd53SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/dac6573.pdf 153593cd53SAlexander A. Klimov * https://www.ti.com/lit/ds/symlink/dac7573.pdf 16df38a4a7SSean Nyekjaer */ 17df38a4a7SSean Nyekjaer 18df38a4a7SSean Nyekjaer #include <linux/iio/iio.h> 19df38a4a7SSean Nyekjaer #include <linux/i2c.h> 20df38a4a7SSean Nyekjaer #include <linux/module.h> 2116723c6eSJonathan Cameron #include <linux/mod_devicetable.h> 22df38a4a7SSean Nyekjaer #include <linux/regulator/consumer.h> 23df38a4a7SSean Nyekjaer 24df38a4a7SSean Nyekjaer enum chip_id { 25df38a4a7SSean Nyekjaer single_8bit, single_10bit, single_12bit, 26df38a4a7SSean Nyekjaer quad_8bit, quad_10bit, quad_12bit 27df38a4a7SSean Nyekjaer }; 28df38a4a7SSean Nyekjaer 29df38a4a7SSean Nyekjaer struct dac5571_spec { 30df38a4a7SSean Nyekjaer u8 num_channels; 31df38a4a7SSean Nyekjaer u8 resolution; 32df38a4a7SSean Nyekjaer }; 33df38a4a7SSean Nyekjaer 34df38a4a7SSean Nyekjaer static const struct dac5571_spec dac5571_spec[] = { 35df38a4a7SSean Nyekjaer [single_8bit] = {.num_channels = 1, .resolution = 8}, 36df38a4a7SSean Nyekjaer [single_10bit] = {.num_channels = 1, .resolution = 10}, 37df38a4a7SSean Nyekjaer [single_12bit] = {.num_channels = 1, .resolution = 12}, 38df38a4a7SSean Nyekjaer [quad_8bit] = {.num_channels = 4, .resolution = 8}, 39df38a4a7SSean Nyekjaer [quad_10bit] = {.num_channels = 4, .resolution = 10}, 40df38a4a7SSean Nyekjaer [quad_12bit] = {.num_channels = 4, .resolution = 12}, 41df38a4a7SSean Nyekjaer }; 42df38a4a7SSean Nyekjaer 43df38a4a7SSean Nyekjaer struct dac5571_data { 44df38a4a7SSean Nyekjaer struct i2c_client *client; 45df38a4a7SSean Nyekjaer int id; 46df38a4a7SSean Nyekjaer struct mutex lock; 47df38a4a7SSean Nyekjaer struct regulator *vref; 48df38a4a7SSean Nyekjaer u16 val[4]; 495dfb88afSVincent Whitchurch bool powerdown[4]; 505dfb88afSVincent Whitchurch u8 powerdown_mode[4]; 51df38a4a7SSean Nyekjaer struct dac5571_spec const *spec; 52df38a4a7SSean Nyekjaer int (*dac5571_cmd)(struct dac5571_data *data, int channel, u16 val); 53df38a4a7SSean Nyekjaer int (*dac5571_pwrdwn)(struct dac5571_data *data, int channel, u8 pwrdwn); 54df38a4a7SSean Nyekjaer u8 buf[3] ____cacheline_aligned; 55df38a4a7SSean Nyekjaer }; 56df38a4a7SSean Nyekjaer 57df38a4a7SSean Nyekjaer #define DAC5571_POWERDOWN(mode) ((mode) + 1) 58df38a4a7SSean Nyekjaer #define DAC5571_POWERDOWN_FLAG BIT(0) 59df38a4a7SSean Nyekjaer #define DAC5571_CHANNEL_SELECT 1 60df38a4a7SSean Nyekjaer #define DAC5571_LOADMODE_DIRECT BIT(4) 61df38a4a7SSean Nyekjaer #define DAC5571_SINGLE_PWRDWN_BITS 4 62df38a4a7SSean Nyekjaer #define DAC5571_QUAD_PWRDWN_BITS 6 63df38a4a7SSean Nyekjaer 64df38a4a7SSean Nyekjaer static int dac5571_cmd_single(struct dac5571_data *data, int channel, u16 val) 65df38a4a7SSean Nyekjaer { 66df38a4a7SSean Nyekjaer unsigned int shift; 67df38a4a7SSean Nyekjaer 68df38a4a7SSean Nyekjaer shift = 12 - data->spec->resolution; 69df38a4a7SSean Nyekjaer data->buf[1] = val << shift; 70df38a4a7SSean Nyekjaer data->buf[0] = val >> (8 - shift); 71df38a4a7SSean Nyekjaer 72df38a4a7SSean Nyekjaer if (i2c_master_send(data->client, data->buf, 2) != 2) 73df38a4a7SSean Nyekjaer return -EIO; 74df38a4a7SSean Nyekjaer 75df38a4a7SSean Nyekjaer return 0; 76df38a4a7SSean Nyekjaer } 77df38a4a7SSean Nyekjaer 78df38a4a7SSean Nyekjaer static int dac5571_cmd_quad(struct dac5571_data *data, int channel, u16 val) 79df38a4a7SSean Nyekjaer { 80df38a4a7SSean Nyekjaer unsigned int shift; 81df38a4a7SSean Nyekjaer 82df38a4a7SSean Nyekjaer shift = 16 - data->spec->resolution; 83df38a4a7SSean Nyekjaer data->buf[2] = val << shift; 84df38a4a7SSean Nyekjaer data->buf[1] = (val >> (8 - shift)); 85df38a4a7SSean Nyekjaer data->buf[0] = (channel << DAC5571_CHANNEL_SELECT) | 86df38a4a7SSean Nyekjaer DAC5571_LOADMODE_DIRECT; 87df38a4a7SSean Nyekjaer 88df38a4a7SSean Nyekjaer if (i2c_master_send(data->client, data->buf, 3) != 3) 89df38a4a7SSean Nyekjaer return -EIO; 90df38a4a7SSean Nyekjaer 91df38a4a7SSean Nyekjaer return 0; 92df38a4a7SSean Nyekjaer } 93df38a4a7SSean Nyekjaer 94df38a4a7SSean Nyekjaer static int dac5571_pwrdwn_single(struct dac5571_data *data, int channel, u8 pwrdwn) 95df38a4a7SSean Nyekjaer { 96df38a4a7SSean Nyekjaer data->buf[1] = 0; 97df38a4a7SSean Nyekjaer data->buf[0] = pwrdwn << DAC5571_SINGLE_PWRDWN_BITS; 98df38a4a7SSean Nyekjaer 99df38a4a7SSean Nyekjaer if (i2c_master_send(data->client, data->buf, 2) != 2) 100df38a4a7SSean Nyekjaer return -EIO; 101df38a4a7SSean Nyekjaer 102df38a4a7SSean Nyekjaer return 0; 103df38a4a7SSean Nyekjaer } 104df38a4a7SSean Nyekjaer 105df38a4a7SSean Nyekjaer static int dac5571_pwrdwn_quad(struct dac5571_data *data, int channel, u8 pwrdwn) 106df38a4a7SSean Nyekjaer { 107df38a4a7SSean Nyekjaer data->buf[2] = 0; 108df38a4a7SSean Nyekjaer data->buf[1] = pwrdwn << DAC5571_QUAD_PWRDWN_BITS; 109df38a4a7SSean Nyekjaer data->buf[0] = (channel << DAC5571_CHANNEL_SELECT) | 110df38a4a7SSean Nyekjaer DAC5571_LOADMODE_DIRECT | DAC5571_POWERDOWN_FLAG; 111df38a4a7SSean Nyekjaer 112df38a4a7SSean Nyekjaer if (i2c_master_send(data->client, data->buf, 3) != 3) 113df38a4a7SSean Nyekjaer return -EIO; 114df38a4a7SSean Nyekjaer 115df38a4a7SSean Nyekjaer return 0; 116df38a4a7SSean Nyekjaer } 117df38a4a7SSean Nyekjaer 118df38a4a7SSean Nyekjaer static const char *const dac5571_powerdown_modes[] = { 119df38a4a7SSean Nyekjaer "1kohm_to_gnd", "100kohm_to_gnd", "three_state", 120df38a4a7SSean Nyekjaer }; 121df38a4a7SSean Nyekjaer 122df38a4a7SSean Nyekjaer static int dac5571_get_powerdown_mode(struct iio_dev *indio_dev, 123df38a4a7SSean Nyekjaer const struct iio_chan_spec *chan) 124df38a4a7SSean Nyekjaer { 125df38a4a7SSean Nyekjaer struct dac5571_data *data = iio_priv(indio_dev); 126df38a4a7SSean Nyekjaer 1275dfb88afSVincent Whitchurch return data->powerdown_mode[chan->channel]; 128df38a4a7SSean Nyekjaer } 129df38a4a7SSean Nyekjaer 130df38a4a7SSean Nyekjaer static int dac5571_set_powerdown_mode(struct iio_dev *indio_dev, 131df38a4a7SSean Nyekjaer const struct iio_chan_spec *chan, 132df38a4a7SSean Nyekjaer unsigned int mode) 133df38a4a7SSean Nyekjaer { 134df38a4a7SSean Nyekjaer struct dac5571_data *data = iio_priv(indio_dev); 135df38a4a7SSean Nyekjaer int ret = 0; 136df38a4a7SSean Nyekjaer 1375dfb88afSVincent Whitchurch if (data->powerdown_mode[chan->channel] == mode) 138df38a4a7SSean Nyekjaer return 0; 139df38a4a7SSean Nyekjaer 140df38a4a7SSean Nyekjaer mutex_lock(&data->lock); 1415dfb88afSVincent Whitchurch if (data->powerdown[chan->channel]) { 142df38a4a7SSean Nyekjaer ret = data->dac5571_pwrdwn(data, chan->channel, 143df38a4a7SSean Nyekjaer DAC5571_POWERDOWN(mode)); 144df38a4a7SSean Nyekjaer if (ret) 145df38a4a7SSean Nyekjaer goto out; 146df38a4a7SSean Nyekjaer } 1475dfb88afSVincent Whitchurch data->powerdown_mode[chan->channel] = mode; 148df38a4a7SSean Nyekjaer 149df38a4a7SSean Nyekjaer out: 150df38a4a7SSean Nyekjaer mutex_unlock(&data->lock); 151df38a4a7SSean Nyekjaer 152df38a4a7SSean Nyekjaer return ret; 153df38a4a7SSean Nyekjaer } 154df38a4a7SSean Nyekjaer 155df38a4a7SSean Nyekjaer static const struct iio_enum dac5571_powerdown_mode = { 156df38a4a7SSean Nyekjaer .items = dac5571_powerdown_modes, 157df38a4a7SSean Nyekjaer .num_items = ARRAY_SIZE(dac5571_powerdown_modes), 158df38a4a7SSean Nyekjaer .get = dac5571_get_powerdown_mode, 159df38a4a7SSean Nyekjaer .set = dac5571_set_powerdown_mode, 160df38a4a7SSean Nyekjaer }; 161df38a4a7SSean Nyekjaer 162df38a4a7SSean Nyekjaer static ssize_t dac5571_read_powerdown(struct iio_dev *indio_dev, 163df38a4a7SSean Nyekjaer uintptr_t private, 164df38a4a7SSean Nyekjaer const struct iio_chan_spec *chan, 165df38a4a7SSean Nyekjaer char *buf) 166df38a4a7SSean Nyekjaer { 167df38a4a7SSean Nyekjaer struct dac5571_data *data = iio_priv(indio_dev); 168df38a4a7SSean Nyekjaer 169f46ac009SLars-Peter Clausen return sysfs_emit(buf, "%d\n", data->powerdown[chan->channel]); 170df38a4a7SSean Nyekjaer } 171df38a4a7SSean Nyekjaer 172df38a4a7SSean Nyekjaer static ssize_t dac5571_write_powerdown(struct iio_dev *indio_dev, 173df38a4a7SSean Nyekjaer uintptr_t private, 174df38a4a7SSean Nyekjaer const struct iio_chan_spec *chan, 175df38a4a7SSean Nyekjaer const char *buf, size_t len) 176df38a4a7SSean Nyekjaer { 177df38a4a7SSean Nyekjaer struct dac5571_data *data = iio_priv(indio_dev); 178df38a4a7SSean Nyekjaer bool powerdown; 179df38a4a7SSean Nyekjaer int ret; 180df38a4a7SSean Nyekjaer 181df38a4a7SSean Nyekjaer ret = strtobool(buf, &powerdown); 182df38a4a7SSean Nyekjaer if (ret) 183df38a4a7SSean Nyekjaer return ret; 184df38a4a7SSean Nyekjaer 1855dfb88afSVincent Whitchurch if (data->powerdown[chan->channel] == powerdown) 186df38a4a7SSean Nyekjaer return len; 187df38a4a7SSean Nyekjaer 188df38a4a7SSean Nyekjaer mutex_lock(&data->lock); 189df38a4a7SSean Nyekjaer if (powerdown) 190df38a4a7SSean Nyekjaer ret = data->dac5571_pwrdwn(data, chan->channel, 1915dfb88afSVincent Whitchurch DAC5571_POWERDOWN(data->powerdown_mode[chan->channel])); 192df38a4a7SSean Nyekjaer else 1935dfb88afSVincent Whitchurch ret = data->dac5571_cmd(data, chan->channel, 1945dfb88afSVincent Whitchurch data->val[chan->channel]); 195df38a4a7SSean Nyekjaer if (ret) 196df38a4a7SSean Nyekjaer goto out; 197df38a4a7SSean Nyekjaer 1985dfb88afSVincent Whitchurch data->powerdown[chan->channel] = powerdown; 199df38a4a7SSean Nyekjaer 200df38a4a7SSean Nyekjaer out: 201df38a4a7SSean Nyekjaer mutex_unlock(&data->lock); 202df38a4a7SSean Nyekjaer 203df38a4a7SSean Nyekjaer return ret ? ret : len; 204df38a4a7SSean Nyekjaer } 205df38a4a7SSean Nyekjaer 206df38a4a7SSean Nyekjaer 207df38a4a7SSean Nyekjaer static const struct iio_chan_spec_ext_info dac5571_ext_info[] = { 208df38a4a7SSean Nyekjaer { 209df38a4a7SSean Nyekjaer .name = "powerdown", 210df38a4a7SSean Nyekjaer .read = dac5571_read_powerdown, 211df38a4a7SSean Nyekjaer .write = dac5571_write_powerdown, 2125dfb88afSVincent Whitchurch .shared = IIO_SEPARATE, 213df38a4a7SSean Nyekjaer }, 2145dfb88afSVincent Whitchurch IIO_ENUM("powerdown_mode", IIO_SEPARATE, &dac5571_powerdown_mode), 215*ffc7c517SAntoniu Miclaus IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &dac5571_powerdown_mode), 216df38a4a7SSean Nyekjaer {}, 217df38a4a7SSean Nyekjaer }; 218df38a4a7SSean Nyekjaer 219df38a4a7SSean Nyekjaer #define dac5571_CHANNEL(chan, name) { \ 220df38a4a7SSean Nyekjaer .type = IIO_VOLTAGE, \ 221df38a4a7SSean Nyekjaer .channel = (chan), \ 222df38a4a7SSean Nyekjaer .address = (chan), \ 223df38a4a7SSean Nyekjaer .indexed = true, \ 224df38a4a7SSean Nyekjaer .output = true, \ 225df38a4a7SSean Nyekjaer .datasheet_name = name, \ 226df38a4a7SSean Nyekjaer .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 227df38a4a7SSean Nyekjaer .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 228df38a4a7SSean Nyekjaer .ext_info = dac5571_ext_info, \ 229df38a4a7SSean Nyekjaer } 230df38a4a7SSean Nyekjaer 231df38a4a7SSean Nyekjaer static const struct iio_chan_spec dac5571_channels[] = { 232df38a4a7SSean Nyekjaer dac5571_CHANNEL(0, "A"), 233df38a4a7SSean Nyekjaer dac5571_CHANNEL(1, "B"), 234df38a4a7SSean Nyekjaer dac5571_CHANNEL(2, "C"), 235df38a4a7SSean Nyekjaer dac5571_CHANNEL(3, "D"), 236df38a4a7SSean Nyekjaer }; 237df38a4a7SSean Nyekjaer 238df38a4a7SSean Nyekjaer static int dac5571_read_raw(struct iio_dev *indio_dev, 239df38a4a7SSean Nyekjaer struct iio_chan_spec const *chan, 240df38a4a7SSean Nyekjaer int *val, int *val2, long mask) 241df38a4a7SSean Nyekjaer { 242df38a4a7SSean Nyekjaer struct dac5571_data *data = iio_priv(indio_dev); 243df38a4a7SSean Nyekjaer int ret; 244df38a4a7SSean Nyekjaer 245df38a4a7SSean Nyekjaer switch (mask) { 246df38a4a7SSean Nyekjaer case IIO_CHAN_INFO_RAW: 247df38a4a7SSean Nyekjaer *val = data->val[chan->channel]; 248df38a4a7SSean Nyekjaer return IIO_VAL_INT; 249df38a4a7SSean Nyekjaer 250df38a4a7SSean Nyekjaer case IIO_CHAN_INFO_SCALE: 251df38a4a7SSean Nyekjaer ret = regulator_get_voltage(data->vref); 252df38a4a7SSean Nyekjaer if (ret < 0) 253df38a4a7SSean Nyekjaer return ret; 254df38a4a7SSean Nyekjaer 255df38a4a7SSean Nyekjaer *val = ret / 1000; 256df38a4a7SSean Nyekjaer *val2 = data->spec->resolution; 257df38a4a7SSean Nyekjaer return IIO_VAL_FRACTIONAL_LOG2; 258df38a4a7SSean Nyekjaer 259df38a4a7SSean Nyekjaer default: 260df38a4a7SSean Nyekjaer return -EINVAL; 261df38a4a7SSean Nyekjaer } 262df38a4a7SSean Nyekjaer } 263df38a4a7SSean Nyekjaer 264df38a4a7SSean Nyekjaer static int dac5571_write_raw(struct iio_dev *indio_dev, 265df38a4a7SSean Nyekjaer struct iio_chan_spec const *chan, 266df38a4a7SSean Nyekjaer int val, int val2, long mask) 267df38a4a7SSean Nyekjaer { 268df38a4a7SSean Nyekjaer struct dac5571_data *data = iio_priv(indio_dev); 269df38a4a7SSean Nyekjaer int ret; 270df38a4a7SSean Nyekjaer 271df38a4a7SSean Nyekjaer switch (mask) { 272df38a4a7SSean Nyekjaer case IIO_CHAN_INFO_RAW: 273df38a4a7SSean Nyekjaer if (data->val[chan->channel] == val) 274df38a4a7SSean Nyekjaer return 0; 275df38a4a7SSean Nyekjaer 276df38a4a7SSean Nyekjaer if (val >= (1 << data->spec->resolution) || val < 0) 277df38a4a7SSean Nyekjaer return -EINVAL; 278df38a4a7SSean Nyekjaer 2795dfb88afSVincent Whitchurch if (data->powerdown[chan->channel]) 280df38a4a7SSean Nyekjaer return -EBUSY; 281df38a4a7SSean Nyekjaer 282df38a4a7SSean Nyekjaer mutex_lock(&data->lock); 283df38a4a7SSean Nyekjaer ret = data->dac5571_cmd(data, chan->channel, val); 284df38a4a7SSean Nyekjaer if (ret == 0) 285df38a4a7SSean Nyekjaer data->val[chan->channel] = val; 286df38a4a7SSean Nyekjaer mutex_unlock(&data->lock); 287df38a4a7SSean Nyekjaer return ret; 288df38a4a7SSean Nyekjaer 289df38a4a7SSean Nyekjaer default: 290df38a4a7SSean Nyekjaer return -EINVAL; 291df38a4a7SSean Nyekjaer } 292df38a4a7SSean Nyekjaer } 293df38a4a7SSean Nyekjaer 294df38a4a7SSean Nyekjaer static int dac5571_write_raw_get_fmt(struct iio_dev *indio_dev, 295df38a4a7SSean Nyekjaer struct iio_chan_spec const *chan, 296df38a4a7SSean Nyekjaer long mask) 297df38a4a7SSean Nyekjaer { 298df38a4a7SSean Nyekjaer return IIO_VAL_INT; 299df38a4a7SSean Nyekjaer } 300df38a4a7SSean Nyekjaer 301df38a4a7SSean Nyekjaer static const struct iio_info dac5571_info = { 302df38a4a7SSean Nyekjaer .read_raw = dac5571_read_raw, 303df38a4a7SSean Nyekjaer .write_raw = dac5571_write_raw, 304df38a4a7SSean Nyekjaer .write_raw_get_fmt = dac5571_write_raw_get_fmt, 305df38a4a7SSean Nyekjaer }; 306df38a4a7SSean Nyekjaer 307df38a4a7SSean Nyekjaer static int dac5571_probe(struct i2c_client *client, 308df38a4a7SSean Nyekjaer const struct i2c_device_id *id) 309df38a4a7SSean Nyekjaer { 310df38a4a7SSean Nyekjaer struct device *dev = &client->dev; 311df38a4a7SSean Nyekjaer const struct dac5571_spec *spec; 312df38a4a7SSean Nyekjaer struct dac5571_data *data; 313df38a4a7SSean Nyekjaer struct iio_dev *indio_dev; 314df38a4a7SSean Nyekjaer int ret, i; 315df38a4a7SSean Nyekjaer 316df38a4a7SSean Nyekjaer indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 317df38a4a7SSean Nyekjaer if (!indio_dev) 318df38a4a7SSean Nyekjaer return -ENOMEM; 319df38a4a7SSean Nyekjaer 320df38a4a7SSean Nyekjaer data = iio_priv(indio_dev); 321df38a4a7SSean Nyekjaer i2c_set_clientdata(client, indio_dev); 322df38a4a7SSean Nyekjaer data->client = client; 323df38a4a7SSean Nyekjaer 324df38a4a7SSean Nyekjaer indio_dev->info = &dac5571_info; 325df38a4a7SSean Nyekjaer indio_dev->name = id->name; 326df38a4a7SSean Nyekjaer indio_dev->modes = INDIO_DIRECT_MODE; 327df38a4a7SSean Nyekjaer indio_dev->channels = dac5571_channels; 328df38a4a7SSean Nyekjaer 329df38a4a7SSean Nyekjaer spec = &dac5571_spec[id->driver_data]; 330df38a4a7SSean Nyekjaer indio_dev->num_channels = spec->num_channels; 331df38a4a7SSean Nyekjaer data->spec = spec; 332df38a4a7SSean Nyekjaer 333df38a4a7SSean Nyekjaer data->vref = devm_regulator_get(dev, "vref"); 334df38a4a7SSean Nyekjaer if (IS_ERR(data->vref)) 335df38a4a7SSean Nyekjaer return PTR_ERR(data->vref); 336df38a4a7SSean Nyekjaer 337df38a4a7SSean Nyekjaer ret = regulator_enable(data->vref); 338df38a4a7SSean Nyekjaer if (ret < 0) 339df38a4a7SSean Nyekjaer return ret; 340df38a4a7SSean Nyekjaer 341df38a4a7SSean Nyekjaer mutex_init(&data->lock); 342df38a4a7SSean Nyekjaer 343df38a4a7SSean Nyekjaer switch (spec->num_channels) { 344df38a4a7SSean Nyekjaer case 1: 345df38a4a7SSean Nyekjaer data->dac5571_cmd = dac5571_cmd_single; 346df38a4a7SSean Nyekjaer data->dac5571_pwrdwn = dac5571_pwrdwn_single; 347df38a4a7SSean Nyekjaer break; 348df38a4a7SSean Nyekjaer case 4: 349df38a4a7SSean Nyekjaer data->dac5571_cmd = dac5571_cmd_quad; 350df38a4a7SSean Nyekjaer data->dac5571_pwrdwn = dac5571_pwrdwn_quad; 351df38a4a7SSean Nyekjaer break; 352df38a4a7SSean Nyekjaer default: 353f7a28df7SDan Carpenter ret = -EINVAL; 354df38a4a7SSean Nyekjaer goto err; 355df38a4a7SSean Nyekjaer } 356df38a4a7SSean Nyekjaer 357df38a4a7SSean Nyekjaer for (i = 0; i < spec->num_channels; i++) { 358df38a4a7SSean Nyekjaer ret = data->dac5571_cmd(data, i, 0); 359df38a4a7SSean Nyekjaer if (ret) { 360df38a4a7SSean Nyekjaer dev_err(dev, "failed to initialize channel %d to 0\n", i); 361df38a4a7SSean Nyekjaer goto err; 362df38a4a7SSean Nyekjaer } 363df38a4a7SSean Nyekjaer } 364df38a4a7SSean Nyekjaer 365df38a4a7SSean Nyekjaer ret = iio_device_register(indio_dev); 366df38a4a7SSean Nyekjaer if (ret) 367df38a4a7SSean Nyekjaer goto err; 368df38a4a7SSean Nyekjaer 369df38a4a7SSean Nyekjaer return 0; 370df38a4a7SSean Nyekjaer 371df38a4a7SSean Nyekjaer err: 372df38a4a7SSean Nyekjaer regulator_disable(data->vref); 373df38a4a7SSean Nyekjaer return ret; 374df38a4a7SSean Nyekjaer } 375df38a4a7SSean Nyekjaer 376df38a4a7SSean Nyekjaer static int dac5571_remove(struct i2c_client *i2c) 377df38a4a7SSean Nyekjaer { 378df38a4a7SSean Nyekjaer struct iio_dev *indio_dev = i2c_get_clientdata(i2c); 379df38a4a7SSean Nyekjaer struct dac5571_data *data = iio_priv(indio_dev); 380df38a4a7SSean Nyekjaer 381df38a4a7SSean Nyekjaer iio_device_unregister(indio_dev); 382df38a4a7SSean Nyekjaer regulator_disable(data->vref); 383df38a4a7SSean Nyekjaer 384df38a4a7SSean Nyekjaer return 0; 385df38a4a7SSean Nyekjaer } 386df38a4a7SSean Nyekjaer 387df38a4a7SSean Nyekjaer static const struct of_device_id dac5571_of_id[] = { 388df38a4a7SSean Nyekjaer {.compatible = "ti,dac5571"}, 389df38a4a7SSean Nyekjaer {.compatible = "ti,dac6571"}, 390df38a4a7SSean Nyekjaer {.compatible = "ti,dac7571"}, 391df38a4a7SSean Nyekjaer {.compatible = "ti,dac5574"}, 392df38a4a7SSean Nyekjaer {.compatible = "ti,dac6574"}, 393df38a4a7SSean Nyekjaer {.compatible = "ti,dac7574"}, 394df38a4a7SSean Nyekjaer {.compatible = "ti,dac5573"}, 395df38a4a7SSean Nyekjaer {.compatible = "ti,dac6573"}, 396df38a4a7SSean Nyekjaer {.compatible = "ti,dac7573"}, 397df38a4a7SSean Nyekjaer {} 398df38a4a7SSean Nyekjaer }; 399df38a4a7SSean Nyekjaer MODULE_DEVICE_TABLE(of, dac5571_of_id); 400df38a4a7SSean Nyekjaer 401df38a4a7SSean Nyekjaer static const struct i2c_device_id dac5571_id[] = { 402df38a4a7SSean Nyekjaer {"dac5571", single_8bit}, 403df38a4a7SSean Nyekjaer {"dac6571", single_10bit}, 404df38a4a7SSean Nyekjaer {"dac7571", single_12bit}, 405df38a4a7SSean Nyekjaer {"dac5574", quad_8bit}, 406df38a4a7SSean Nyekjaer {"dac6574", quad_10bit}, 407df38a4a7SSean Nyekjaer {"dac7574", quad_12bit}, 408df38a4a7SSean Nyekjaer {"dac5573", quad_8bit}, 409df38a4a7SSean Nyekjaer {"dac6573", quad_10bit}, 410df38a4a7SSean Nyekjaer {"dac7573", quad_12bit}, 411df38a4a7SSean Nyekjaer {} 412df38a4a7SSean Nyekjaer }; 413df38a4a7SSean Nyekjaer MODULE_DEVICE_TABLE(i2c, dac5571_id); 414df38a4a7SSean Nyekjaer 415df38a4a7SSean Nyekjaer static struct i2c_driver dac5571_driver = { 416df38a4a7SSean Nyekjaer .driver = { 417df38a4a7SSean Nyekjaer .name = "ti-dac5571", 41816723c6eSJonathan Cameron .of_match_table = dac5571_of_id, 419df38a4a7SSean Nyekjaer }, 420df38a4a7SSean Nyekjaer .probe = dac5571_probe, 421df38a4a7SSean Nyekjaer .remove = dac5571_remove, 422df38a4a7SSean Nyekjaer .id_table = dac5571_id, 423df38a4a7SSean Nyekjaer }; 424df38a4a7SSean Nyekjaer module_i2c_driver(dac5571_driver); 425df38a4a7SSean Nyekjaer 426d43102f5SSean Nyekjaer MODULE_AUTHOR("Sean Nyekjaer <sean@geanix.dk>"); 427df38a4a7SSean Nyekjaer MODULE_DESCRIPTION("Texas Instruments 8/10/12-bit 1/4-channel DAC driver"); 428df38a4a7SSean Nyekjaer MODULE_LICENSE("GPL v2"); 429