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