1*dbdc025bSLars-Peter Clausen /* 2*dbdc025bSLars-Peter Clausen * Analog devices AD5360, AD5361, AD5362, AD5363, AD5370, AD5371, AD5373 3*dbdc025bSLars-Peter Clausen * multi-channel Digital to Analog Converters driver 4*dbdc025bSLars-Peter Clausen * 5*dbdc025bSLars-Peter Clausen * Copyright 2011 Analog Devices Inc. 6*dbdc025bSLars-Peter Clausen * 7*dbdc025bSLars-Peter Clausen * Licensed under the GPL-2. 8*dbdc025bSLars-Peter Clausen */ 9*dbdc025bSLars-Peter Clausen 10*dbdc025bSLars-Peter Clausen #include <linux/device.h> 11*dbdc025bSLars-Peter Clausen #include <linux/err.h> 12*dbdc025bSLars-Peter Clausen #include <linux/module.h> 13*dbdc025bSLars-Peter Clausen #include <linux/kernel.h> 14*dbdc025bSLars-Peter Clausen #include <linux/spi/spi.h> 15*dbdc025bSLars-Peter Clausen #include <linux/slab.h> 16*dbdc025bSLars-Peter Clausen #include <linux/sysfs.h> 17*dbdc025bSLars-Peter Clausen #include <linux/regulator/consumer.h> 18*dbdc025bSLars-Peter Clausen 19*dbdc025bSLars-Peter Clausen #include <linux/iio/iio.h> 20*dbdc025bSLars-Peter Clausen #include <linux/iio/sysfs.h> 21*dbdc025bSLars-Peter Clausen 22*dbdc025bSLars-Peter Clausen #define AD5360_CMD(x) ((x) << 22) 23*dbdc025bSLars-Peter Clausen #define AD5360_ADDR(x) ((x) << 16) 24*dbdc025bSLars-Peter Clausen 25*dbdc025bSLars-Peter Clausen #define AD5360_READBACK_TYPE(x) ((x) << 13) 26*dbdc025bSLars-Peter Clausen #define AD5360_READBACK_ADDR(x) ((x) << 7) 27*dbdc025bSLars-Peter Clausen 28*dbdc025bSLars-Peter Clausen #define AD5360_CHAN_ADDR(chan) ((chan) + 0x8) 29*dbdc025bSLars-Peter Clausen 30*dbdc025bSLars-Peter Clausen #define AD5360_CMD_WRITE_DATA 0x3 31*dbdc025bSLars-Peter Clausen #define AD5360_CMD_WRITE_OFFSET 0x2 32*dbdc025bSLars-Peter Clausen #define AD5360_CMD_WRITE_GAIN 0x1 33*dbdc025bSLars-Peter Clausen #define AD5360_CMD_SPECIAL_FUNCTION 0x0 34*dbdc025bSLars-Peter Clausen 35*dbdc025bSLars-Peter Clausen /* Special function register addresses */ 36*dbdc025bSLars-Peter Clausen #define AD5360_REG_SF_NOP 0x0 37*dbdc025bSLars-Peter Clausen #define AD5360_REG_SF_CTRL 0x1 38*dbdc025bSLars-Peter Clausen #define AD5360_REG_SF_OFS(x) (0x2 + (x)) 39*dbdc025bSLars-Peter Clausen #define AD5360_REG_SF_READBACK 0x5 40*dbdc025bSLars-Peter Clausen 41*dbdc025bSLars-Peter Clausen #define AD5360_SF_CTRL_PWR_DOWN BIT(0) 42*dbdc025bSLars-Peter Clausen 43*dbdc025bSLars-Peter Clausen #define AD5360_READBACK_X1A 0x0 44*dbdc025bSLars-Peter Clausen #define AD5360_READBACK_X1B 0x1 45*dbdc025bSLars-Peter Clausen #define AD5360_READBACK_OFFSET 0x2 46*dbdc025bSLars-Peter Clausen #define AD5360_READBACK_GAIN 0x3 47*dbdc025bSLars-Peter Clausen #define AD5360_READBACK_SF 0x4 48*dbdc025bSLars-Peter Clausen 49*dbdc025bSLars-Peter Clausen 50*dbdc025bSLars-Peter Clausen /** 51*dbdc025bSLars-Peter Clausen * struct ad5360_chip_info - chip specific information 52*dbdc025bSLars-Peter Clausen * @channel_template: channel specification template 53*dbdc025bSLars-Peter Clausen * @num_channels: number of channels 54*dbdc025bSLars-Peter Clausen * @channels_per_group: number of channels per group 55*dbdc025bSLars-Peter Clausen * @num_vrefs: number of vref supplies for the chip 56*dbdc025bSLars-Peter Clausen */ 57*dbdc025bSLars-Peter Clausen 58*dbdc025bSLars-Peter Clausen struct ad5360_chip_info { 59*dbdc025bSLars-Peter Clausen struct iio_chan_spec channel_template; 60*dbdc025bSLars-Peter Clausen unsigned int num_channels; 61*dbdc025bSLars-Peter Clausen unsigned int channels_per_group; 62*dbdc025bSLars-Peter Clausen unsigned int num_vrefs; 63*dbdc025bSLars-Peter Clausen }; 64*dbdc025bSLars-Peter Clausen 65*dbdc025bSLars-Peter Clausen /** 66*dbdc025bSLars-Peter Clausen * struct ad5360_state - driver instance specific data 67*dbdc025bSLars-Peter Clausen * @spi: spi_device 68*dbdc025bSLars-Peter Clausen * @chip_info: chip model specific constants, available modes etc 69*dbdc025bSLars-Peter Clausen * @vref_reg: vref supply regulators 70*dbdc025bSLars-Peter Clausen * @ctrl: control register cache 71*dbdc025bSLars-Peter Clausen * @data: spi transfer buffers 72*dbdc025bSLars-Peter Clausen */ 73*dbdc025bSLars-Peter Clausen 74*dbdc025bSLars-Peter Clausen struct ad5360_state { 75*dbdc025bSLars-Peter Clausen struct spi_device *spi; 76*dbdc025bSLars-Peter Clausen const struct ad5360_chip_info *chip_info; 77*dbdc025bSLars-Peter Clausen struct regulator_bulk_data vref_reg[3]; 78*dbdc025bSLars-Peter Clausen unsigned int ctrl; 79*dbdc025bSLars-Peter Clausen 80*dbdc025bSLars-Peter Clausen /* 81*dbdc025bSLars-Peter Clausen * DMA (thus cache coherency maintenance) requires the 82*dbdc025bSLars-Peter Clausen * transfer buffers to live in their own cache lines. 83*dbdc025bSLars-Peter Clausen */ 84*dbdc025bSLars-Peter Clausen union { 85*dbdc025bSLars-Peter Clausen __be32 d32; 86*dbdc025bSLars-Peter Clausen u8 d8[4]; 87*dbdc025bSLars-Peter Clausen } data[2] ____cacheline_aligned; 88*dbdc025bSLars-Peter Clausen }; 89*dbdc025bSLars-Peter Clausen 90*dbdc025bSLars-Peter Clausen enum ad5360_type { 91*dbdc025bSLars-Peter Clausen ID_AD5360, 92*dbdc025bSLars-Peter Clausen ID_AD5361, 93*dbdc025bSLars-Peter Clausen ID_AD5362, 94*dbdc025bSLars-Peter Clausen ID_AD5363, 95*dbdc025bSLars-Peter Clausen ID_AD5370, 96*dbdc025bSLars-Peter Clausen ID_AD5371, 97*dbdc025bSLars-Peter Clausen ID_AD5372, 98*dbdc025bSLars-Peter Clausen ID_AD5373, 99*dbdc025bSLars-Peter Clausen }; 100*dbdc025bSLars-Peter Clausen 101*dbdc025bSLars-Peter Clausen #define AD5360_CHANNEL(bits) { \ 102*dbdc025bSLars-Peter Clausen .type = IIO_VOLTAGE, \ 103*dbdc025bSLars-Peter Clausen .indexed = 1, \ 104*dbdc025bSLars-Peter Clausen .output = 1, \ 105*dbdc025bSLars-Peter Clausen .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ 106*dbdc025bSLars-Peter Clausen IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \ 107*dbdc025bSLars-Peter Clausen IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \ 108*dbdc025bSLars-Peter Clausen IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ 109*dbdc025bSLars-Peter Clausen IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \ 110*dbdc025bSLars-Peter Clausen .scan_type = IIO_ST('u', (bits), 16, 16 - (bits)) \ 111*dbdc025bSLars-Peter Clausen } 112*dbdc025bSLars-Peter Clausen 113*dbdc025bSLars-Peter Clausen static const struct ad5360_chip_info ad5360_chip_info_tbl[] = { 114*dbdc025bSLars-Peter Clausen [ID_AD5360] = { 115*dbdc025bSLars-Peter Clausen .channel_template = AD5360_CHANNEL(16), 116*dbdc025bSLars-Peter Clausen .num_channels = 16, 117*dbdc025bSLars-Peter Clausen .channels_per_group = 8, 118*dbdc025bSLars-Peter Clausen .num_vrefs = 2, 119*dbdc025bSLars-Peter Clausen }, 120*dbdc025bSLars-Peter Clausen [ID_AD5361] = { 121*dbdc025bSLars-Peter Clausen .channel_template = AD5360_CHANNEL(14), 122*dbdc025bSLars-Peter Clausen .num_channels = 16, 123*dbdc025bSLars-Peter Clausen .channels_per_group = 8, 124*dbdc025bSLars-Peter Clausen .num_vrefs = 2, 125*dbdc025bSLars-Peter Clausen }, 126*dbdc025bSLars-Peter Clausen [ID_AD5362] = { 127*dbdc025bSLars-Peter Clausen .channel_template = AD5360_CHANNEL(16), 128*dbdc025bSLars-Peter Clausen .num_channels = 8, 129*dbdc025bSLars-Peter Clausen .channels_per_group = 4, 130*dbdc025bSLars-Peter Clausen .num_vrefs = 2, 131*dbdc025bSLars-Peter Clausen }, 132*dbdc025bSLars-Peter Clausen [ID_AD5363] = { 133*dbdc025bSLars-Peter Clausen .channel_template = AD5360_CHANNEL(14), 134*dbdc025bSLars-Peter Clausen .num_channels = 8, 135*dbdc025bSLars-Peter Clausen .channels_per_group = 4, 136*dbdc025bSLars-Peter Clausen .num_vrefs = 2, 137*dbdc025bSLars-Peter Clausen }, 138*dbdc025bSLars-Peter Clausen [ID_AD5370] = { 139*dbdc025bSLars-Peter Clausen .channel_template = AD5360_CHANNEL(16), 140*dbdc025bSLars-Peter Clausen .num_channels = 40, 141*dbdc025bSLars-Peter Clausen .channels_per_group = 8, 142*dbdc025bSLars-Peter Clausen .num_vrefs = 2, 143*dbdc025bSLars-Peter Clausen }, 144*dbdc025bSLars-Peter Clausen [ID_AD5371] = { 145*dbdc025bSLars-Peter Clausen .channel_template = AD5360_CHANNEL(14), 146*dbdc025bSLars-Peter Clausen .num_channels = 40, 147*dbdc025bSLars-Peter Clausen .channels_per_group = 8, 148*dbdc025bSLars-Peter Clausen .num_vrefs = 3, 149*dbdc025bSLars-Peter Clausen }, 150*dbdc025bSLars-Peter Clausen [ID_AD5372] = { 151*dbdc025bSLars-Peter Clausen .channel_template = AD5360_CHANNEL(16), 152*dbdc025bSLars-Peter Clausen .num_channels = 32, 153*dbdc025bSLars-Peter Clausen .channels_per_group = 8, 154*dbdc025bSLars-Peter Clausen .num_vrefs = 2, 155*dbdc025bSLars-Peter Clausen }, 156*dbdc025bSLars-Peter Clausen [ID_AD5373] = { 157*dbdc025bSLars-Peter Clausen .channel_template = AD5360_CHANNEL(14), 158*dbdc025bSLars-Peter Clausen .num_channels = 32, 159*dbdc025bSLars-Peter Clausen .channels_per_group = 8, 160*dbdc025bSLars-Peter Clausen .num_vrefs = 2, 161*dbdc025bSLars-Peter Clausen }, 162*dbdc025bSLars-Peter Clausen }; 163*dbdc025bSLars-Peter Clausen 164*dbdc025bSLars-Peter Clausen static unsigned int ad5360_get_channel_vref_index(struct ad5360_state *st, 165*dbdc025bSLars-Peter Clausen unsigned int channel) 166*dbdc025bSLars-Peter Clausen { 167*dbdc025bSLars-Peter Clausen unsigned int i; 168*dbdc025bSLars-Peter Clausen 169*dbdc025bSLars-Peter Clausen /* The first groups have their own vref, while the remaining groups 170*dbdc025bSLars-Peter Clausen * share the last vref */ 171*dbdc025bSLars-Peter Clausen i = channel / st->chip_info->channels_per_group; 172*dbdc025bSLars-Peter Clausen if (i >= st->chip_info->num_vrefs) 173*dbdc025bSLars-Peter Clausen i = st->chip_info->num_vrefs - 1; 174*dbdc025bSLars-Peter Clausen 175*dbdc025bSLars-Peter Clausen return i; 176*dbdc025bSLars-Peter Clausen } 177*dbdc025bSLars-Peter Clausen 178*dbdc025bSLars-Peter Clausen static int ad5360_get_channel_vref(struct ad5360_state *st, 179*dbdc025bSLars-Peter Clausen unsigned int channel) 180*dbdc025bSLars-Peter Clausen { 181*dbdc025bSLars-Peter Clausen unsigned int i = ad5360_get_channel_vref_index(st, channel); 182*dbdc025bSLars-Peter Clausen 183*dbdc025bSLars-Peter Clausen return regulator_get_voltage(st->vref_reg[i].consumer); 184*dbdc025bSLars-Peter Clausen } 185*dbdc025bSLars-Peter Clausen 186*dbdc025bSLars-Peter Clausen 187*dbdc025bSLars-Peter Clausen static int ad5360_write_unlocked(struct iio_dev *indio_dev, 188*dbdc025bSLars-Peter Clausen unsigned int cmd, unsigned int addr, unsigned int val, 189*dbdc025bSLars-Peter Clausen unsigned int shift) 190*dbdc025bSLars-Peter Clausen { 191*dbdc025bSLars-Peter Clausen struct ad5360_state *st = iio_priv(indio_dev); 192*dbdc025bSLars-Peter Clausen 193*dbdc025bSLars-Peter Clausen val <<= shift; 194*dbdc025bSLars-Peter Clausen val |= AD5360_CMD(cmd) | AD5360_ADDR(addr); 195*dbdc025bSLars-Peter Clausen st->data[0].d32 = cpu_to_be32(val); 196*dbdc025bSLars-Peter Clausen 197*dbdc025bSLars-Peter Clausen return spi_write(st->spi, &st->data[0].d8[1], 3); 198*dbdc025bSLars-Peter Clausen } 199*dbdc025bSLars-Peter Clausen 200*dbdc025bSLars-Peter Clausen static int ad5360_write(struct iio_dev *indio_dev, unsigned int cmd, 201*dbdc025bSLars-Peter Clausen unsigned int addr, unsigned int val, unsigned int shift) 202*dbdc025bSLars-Peter Clausen { 203*dbdc025bSLars-Peter Clausen int ret; 204*dbdc025bSLars-Peter Clausen 205*dbdc025bSLars-Peter Clausen mutex_lock(&indio_dev->mlock); 206*dbdc025bSLars-Peter Clausen ret = ad5360_write_unlocked(indio_dev, cmd, addr, val, shift); 207*dbdc025bSLars-Peter Clausen mutex_unlock(&indio_dev->mlock); 208*dbdc025bSLars-Peter Clausen 209*dbdc025bSLars-Peter Clausen return ret; 210*dbdc025bSLars-Peter Clausen } 211*dbdc025bSLars-Peter Clausen 212*dbdc025bSLars-Peter Clausen static int ad5360_read(struct iio_dev *indio_dev, unsigned int type, 213*dbdc025bSLars-Peter Clausen unsigned int addr) 214*dbdc025bSLars-Peter Clausen { 215*dbdc025bSLars-Peter Clausen struct ad5360_state *st = iio_priv(indio_dev); 216*dbdc025bSLars-Peter Clausen struct spi_message m; 217*dbdc025bSLars-Peter Clausen int ret; 218*dbdc025bSLars-Peter Clausen struct spi_transfer t[] = { 219*dbdc025bSLars-Peter Clausen { 220*dbdc025bSLars-Peter Clausen .tx_buf = &st->data[0].d8[1], 221*dbdc025bSLars-Peter Clausen .len = 3, 222*dbdc025bSLars-Peter Clausen .cs_change = 1, 223*dbdc025bSLars-Peter Clausen }, { 224*dbdc025bSLars-Peter Clausen .rx_buf = &st->data[1].d8[1], 225*dbdc025bSLars-Peter Clausen .len = 3, 226*dbdc025bSLars-Peter Clausen }, 227*dbdc025bSLars-Peter Clausen }; 228*dbdc025bSLars-Peter Clausen 229*dbdc025bSLars-Peter Clausen spi_message_init(&m); 230*dbdc025bSLars-Peter Clausen spi_message_add_tail(&t[0], &m); 231*dbdc025bSLars-Peter Clausen spi_message_add_tail(&t[1], &m); 232*dbdc025bSLars-Peter Clausen 233*dbdc025bSLars-Peter Clausen mutex_lock(&indio_dev->mlock); 234*dbdc025bSLars-Peter Clausen 235*dbdc025bSLars-Peter Clausen st->data[0].d32 = cpu_to_be32(AD5360_CMD(AD5360_CMD_SPECIAL_FUNCTION) | 236*dbdc025bSLars-Peter Clausen AD5360_ADDR(AD5360_REG_SF_READBACK) | 237*dbdc025bSLars-Peter Clausen AD5360_READBACK_TYPE(type) | 238*dbdc025bSLars-Peter Clausen AD5360_READBACK_ADDR(addr)); 239*dbdc025bSLars-Peter Clausen 240*dbdc025bSLars-Peter Clausen ret = spi_sync(st->spi, &m); 241*dbdc025bSLars-Peter Clausen if (ret >= 0) 242*dbdc025bSLars-Peter Clausen ret = be32_to_cpu(st->data[1].d32) & 0xffff; 243*dbdc025bSLars-Peter Clausen 244*dbdc025bSLars-Peter Clausen mutex_unlock(&indio_dev->mlock); 245*dbdc025bSLars-Peter Clausen 246*dbdc025bSLars-Peter Clausen return ret; 247*dbdc025bSLars-Peter Clausen } 248*dbdc025bSLars-Peter Clausen 249*dbdc025bSLars-Peter Clausen static ssize_t ad5360_read_dac_powerdown(struct device *dev, 250*dbdc025bSLars-Peter Clausen struct device_attribute *attr, 251*dbdc025bSLars-Peter Clausen char *buf) 252*dbdc025bSLars-Peter Clausen { 253*dbdc025bSLars-Peter Clausen struct iio_dev *indio_dev = dev_to_iio_dev(dev); 254*dbdc025bSLars-Peter Clausen struct ad5360_state *st = iio_priv(indio_dev); 255*dbdc025bSLars-Peter Clausen 256*dbdc025bSLars-Peter Clausen return sprintf(buf, "%d\n", (bool)(st->ctrl & AD5360_SF_CTRL_PWR_DOWN)); 257*dbdc025bSLars-Peter Clausen } 258*dbdc025bSLars-Peter Clausen 259*dbdc025bSLars-Peter Clausen static int ad5360_update_ctrl(struct iio_dev *indio_dev, unsigned int set, 260*dbdc025bSLars-Peter Clausen unsigned int clr) 261*dbdc025bSLars-Peter Clausen { 262*dbdc025bSLars-Peter Clausen struct ad5360_state *st = iio_priv(indio_dev); 263*dbdc025bSLars-Peter Clausen unsigned int ret; 264*dbdc025bSLars-Peter Clausen 265*dbdc025bSLars-Peter Clausen mutex_lock(&indio_dev->mlock); 266*dbdc025bSLars-Peter Clausen 267*dbdc025bSLars-Peter Clausen st->ctrl |= set; 268*dbdc025bSLars-Peter Clausen st->ctrl &= ~clr; 269*dbdc025bSLars-Peter Clausen 270*dbdc025bSLars-Peter Clausen ret = ad5360_write_unlocked(indio_dev, AD5360_CMD_SPECIAL_FUNCTION, 271*dbdc025bSLars-Peter Clausen AD5360_REG_SF_CTRL, st->ctrl, 0); 272*dbdc025bSLars-Peter Clausen 273*dbdc025bSLars-Peter Clausen mutex_unlock(&indio_dev->mlock); 274*dbdc025bSLars-Peter Clausen 275*dbdc025bSLars-Peter Clausen return ret; 276*dbdc025bSLars-Peter Clausen } 277*dbdc025bSLars-Peter Clausen 278*dbdc025bSLars-Peter Clausen static ssize_t ad5360_write_dac_powerdown(struct device *dev, 279*dbdc025bSLars-Peter Clausen struct device_attribute *attr, const char *buf, size_t len) 280*dbdc025bSLars-Peter Clausen { 281*dbdc025bSLars-Peter Clausen struct iio_dev *indio_dev = dev_to_iio_dev(dev); 282*dbdc025bSLars-Peter Clausen bool pwr_down; 283*dbdc025bSLars-Peter Clausen int ret; 284*dbdc025bSLars-Peter Clausen 285*dbdc025bSLars-Peter Clausen ret = strtobool(buf, &pwr_down); 286*dbdc025bSLars-Peter Clausen if (ret) 287*dbdc025bSLars-Peter Clausen return ret; 288*dbdc025bSLars-Peter Clausen 289*dbdc025bSLars-Peter Clausen if (pwr_down) 290*dbdc025bSLars-Peter Clausen ret = ad5360_update_ctrl(indio_dev, AD5360_SF_CTRL_PWR_DOWN, 0); 291*dbdc025bSLars-Peter Clausen else 292*dbdc025bSLars-Peter Clausen ret = ad5360_update_ctrl(indio_dev, 0, AD5360_SF_CTRL_PWR_DOWN); 293*dbdc025bSLars-Peter Clausen 294*dbdc025bSLars-Peter Clausen return ret ? ret : len; 295*dbdc025bSLars-Peter Clausen } 296*dbdc025bSLars-Peter Clausen 297*dbdc025bSLars-Peter Clausen static IIO_DEVICE_ATTR(out_voltage_powerdown, 298*dbdc025bSLars-Peter Clausen S_IRUGO | S_IWUSR, 299*dbdc025bSLars-Peter Clausen ad5360_read_dac_powerdown, 300*dbdc025bSLars-Peter Clausen ad5360_write_dac_powerdown, 0); 301*dbdc025bSLars-Peter Clausen 302*dbdc025bSLars-Peter Clausen static struct attribute *ad5360_attributes[] = { 303*dbdc025bSLars-Peter Clausen &iio_dev_attr_out_voltage_powerdown.dev_attr.attr, 304*dbdc025bSLars-Peter Clausen NULL, 305*dbdc025bSLars-Peter Clausen }; 306*dbdc025bSLars-Peter Clausen 307*dbdc025bSLars-Peter Clausen static const struct attribute_group ad5360_attribute_group = { 308*dbdc025bSLars-Peter Clausen .attrs = ad5360_attributes, 309*dbdc025bSLars-Peter Clausen }; 310*dbdc025bSLars-Peter Clausen 311*dbdc025bSLars-Peter Clausen static int ad5360_write_raw(struct iio_dev *indio_dev, 312*dbdc025bSLars-Peter Clausen struct iio_chan_spec const *chan, 313*dbdc025bSLars-Peter Clausen int val, 314*dbdc025bSLars-Peter Clausen int val2, 315*dbdc025bSLars-Peter Clausen long mask) 316*dbdc025bSLars-Peter Clausen { 317*dbdc025bSLars-Peter Clausen struct ad5360_state *st = iio_priv(indio_dev); 318*dbdc025bSLars-Peter Clausen int max_val = (1 << chan->scan_type.realbits); 319*dbdc025bSLars-Peter Clausen unsigned int ofs_index; 320*dbdc025bSLars-Peter Clausen 321*dbdc025bSLars-Peter Clausen switch (mask) { 322*dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_RAW: 323*dbdc025bSLars-Peter Clausen if (val >= max_val || val < 0) 324*dbdc025bSLars-Peter Clausen return -EINVAL; 325*dbdc025bSLars-Peter Clausen 326*dbdc025bSLars-Peter Clausen return ad5360_write(indio_dev, AD5360_CMD_WRITE_DATA, 327*dbdc025bSLars-Peter Clausen chan->address, val, chan->scan_type.shift); 328*dbdc025bSLars-Peter Clausen 329*dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_CALIBBIAS: 330*dbdc025bSLars-Peter Clausen if (val >= max_val || val < 0) 331*dbdc025bSLars-Peter Clausen return -EINVAL; 332*dbdc025bSLars-Peter Clausen 333*dbdc025bSLars-Peter Clausen return ad5360_write(indio_dev, AD5360_CMD_WRITE_OFFSET, 334*dbdc025bSLars-Peter Clausen chan->address, val, chan->scan_type.shift); 335*dbdc025bSLars-Peter Clausen 336*dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_CALIBSCALE: 337*dbdc025bSLars-Peter Clausen if (val >= max_val || val < 0) 338*dbdc025bSLars-Peter Clausen return -EINVAL; 339*dbdc025bSLars-Peter Clausen 340*dbdc025bSLars-Peter Clausen return ad5360_write(indio_dev, AD5360_CMD_WRITE_GAIN, 341*dbdc025bSLars-Peter Clausen chan->address, val, chan->scan_type.shift); 342*dbdc025bSLars-Peter Clausen 343*dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_OFFSET: 344*dbdc025bSLars-Peter Clausen if (val <= -max_val || val > 0) 345*dbdc025bSLars-Peter Clausen return -EINVAL; 346*dbdc025bSLars-Peter Clausen 347*dbdc025bSLars-Peter Clausen val = -val; 348*dbdc025bSLars-Peter Clausen 349*dbdc025bSLars-Peter Clausen /* offset is supposed to have the same scale as raw, but it 350*dbdc025bSLars-Peter Clausen * is always 14bits wide, so on a chip where the raw value has 351*dbdc025bSLars-Peter Clausen * more bits, we need to shift offset. */ 352*dbdc025bSLars-Peter Clausen val >>= (chan->scan_type.realbits - 14); 353*dbdc025bSLars-Peter Clausen 354*dbdc025bSLars-Peter Clausen /* There is one DAC offset register per vref. Changing one 355*dbdc025bSLars-Peter Clausen * channels offset will also change the offset for all other 356*dbdc025bSLars-Peter Clausen * channels which share the same vref supply. */ 357*dbdc025bSLars-Peter Clausen ofs_index = ad5360_get_channel_vref_index(st, chan->channel); 358*dbdc025bSLars-Peter Clausen return ad5360_write(indio_dev, AD5360_CMD_SPECIAL_FUNCTION, 359*dbdc025bSLars-Peter Clausen AD5360_REG_SF_OFS(ofs_index), val, 0); 360*dbdc025bSLars-Peter Clausen default: 361*dbdc025bSLars-Peter Clausen break; 362*dbdc025bSLars-Peter Clausen } 363*dbdc025bSLars-Peter Clausen 364*dbdc025bSLars-Peter Clausen return -EINVAL; 365*dbdc025bSLars-Peter Clausen } 366*dbdc025bSLars-Peter Clausen 367*dbdc025bSLars-Peter Clausen static int ad5360_read_raw(struct iio_dev *indio_dev, 368*dbdc025bSLars-Peter Clausen struct iio_chan_spec const *chan, 369*dbdc025bSLars-Peter Clausen int *val, 370*dbdc025bSLars-Peter Clausen int *val2, 371*dbdc025bSLars-Peter Clausen long m) 372*dbdc025bSLars-Peter Clausen { 373*dbdc025bSLars-Peter Clausen struct ad5360_state *st = iio_priv(indio_dev); 374*dbdc025bSLars-Peter Clausen unsigned int ofs_index; 375*dbdc025bSLars-Peter Clausen int scale_uv; 376*dbdc025bSLars-Peter Clausen int ret; 377*dbdc025bSLars-Peter Clausen 378*dbdc025bSLars-Peter Clausen switch (m) { 379*dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_RAW: 380*dbdc025bSLars-Peter Clausen ret = ad5360_read(indio_dev, AD5360_READBACK_X1A, 381*dbdc025bSLars-Peter Clausen chan->address); 382*dbdc025bSLars-Peter Clausen if (ret < 0) 383*dbdc025bSLars-Peter Clausen return ret; 384*dbdc025bSLars-Peter Clausen *val = ret >> chan->scan_type.shift; 385*dbdc025bSLars-Peter Clausen return IIO_VAL_INT; 386*dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_SCALE: 387*dbdc025bSLars-Peter Clausen /* vout = 4 * vref * dac_code */ 388*dbdc025bSLars-Peter Clausen scale_uv = ad5360_get_channel_vref(st, chan->channel) * 4 * 100; 389*dbdc025bSLars-Peter Clausen if (scale_uv < 0) 390*dbdc025bSLars-Peter Clausen return scale_uv; 391*dbdc025bSLars-Peter Clausen 392*dbdc025bSLars-Peter Clausen scale_uv >>= (chan->scan_type.realbits); 393*dbdc025bSLars-Peter Clausen *val = scale_uv / 100000; 394*dbdc025bSLars-Peter Clausen *val2 = (scale_uv % 100000) * 10; 395*dbdc025bSLars-Peter Clausen return IIO_VAL_INT_PLUS_MICRO; 396*dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_CALIBBIAS: 397*dbdc025bSLars-Peter Clausen ret = ad5360_read(indio_dev, AD5360_READBACK_OFFSET, 398*dbdc025bSLars-Peter Clausen chan->address); 399*dbdc025bSLars-Peter Clausen if (ret < 0) 400*dbdc025bSLars-Peter Clausen return ret; 401*dbdc025bSLars-Peter Clausen *val = ret; 402*dbdc025bSLars-Peter Clausen return IIO_VAL_INT; 403*dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_CALIBSCALE: 404*dbdc025bSLars-Peter Clausen ret = ad5360_read(indio_dev, AD5360_READBACK_GAIN, 405*dbdc025bSLars-Peter Clausen chan->address); 406*dbdc025bSLars-Peter Clausen if (ret < 0) 407*dbdc025bSLars-Peter Clausen return ret; 408*dbdc025bSLars-Peter Clausen *val = ret; 409*dbdc025bSLars-Peter Clausen return IIO_VAL_INT; 410*dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_OFFSET: 411*dbdc025bSLars-Peter Clausen ofs_index = ad5360_get_channel_vref_index(st, chan->channel); 412*dbdc025bSLars-Peter Clausen ret = ad5360_read(indio_dev, AD5360_READBACK_SF, 413*dbdc025bSLars-Peter Clausen AD5360_REG_SF_OFS(ofs_index)); 414*dbdc025bSLars-Peter Clausen if (ret < 0) 415*dbdc025bSLars-Peter Clausen return ret; 416*dbdc025bSLars-Peter Clausen 417*dbdc025bSLars-Peter Clausen ret <<= (chan->scan_type.realbits - 14); 418*dbdc025bSLars-Peter Clausen *val = -ret; 419*dbdc025bSLars-Peter Clausen return IIO_VAL_INT; 420*dbdc025bSLars-Peter Clausen } 421*dbdc025bSLars-Peter Clausen 422*dbdc025bSLars-Peter Clausen return -EINVAL; 423*dbdc025bSLars-Peter Clausen } 424*dbdc025bSLars-Peter Clausen 425*dbdc025bSLars-Peter Clausen static const struct iio_info ad5360_info = { 426*dbdc025bSLars-Peter Clausen .read_raw = ad5360_read_raw, 427*dbdc025bSLars-Peter Clausen .write_raw = ad5360_write_raw, 428*dbdc025bSLars-Peter Clausen .attrs = &ad5360_attribute_group, 429*dbdc025bSLars-Peter Clausen .driver_module = THIS_MODULE, 430*dbdc025bSLars-Peter Clausen }; 431*dbdc025bSLars-Peter Clausen 432*dbdc025bSLars-Peter Clausen static const char * const ad5360_vref_name[] = { 433*dbdc025bSLars-Peter Clausen "vref0", "vref1", "vref2" 434*dbdc025bSLars-Peter Clausen }; 435*dbdc025bSLars-Peter Clausen 436*dbdc025bSLars-Peter Clausen static int __devinit ad5360_alloc_channels(struct iio_dev *indio_dev) 437*dbdc025bSLars-Peter Clausen { 438*dbdc025bSLars-Peter Clausen struct ad5360_state *st = iio_priv(indio_dev); 439*dbdc025bSLars-Peter Clausen struct iio_chan_spec *channels; 440*dbdc025bSLars-Peter Clausen unsigned int i; 441*dbdc025bSLars-Peter Clausen 442*dbdc025bSLars-Peter Clausen channels = kcalloc(st->chip_info->num_channels, 443*dbdc025bSLars-Peter Clausen sizeof(struct iio_chan_spec), GFP_KERNEL); 444*dbdc025bSLars-Peter Clausen 445*dbdc025bSLars-Peter Clausen if (!channels) 446*dbdc025bSLars-Peter Clausen return -ENOMEM; 447*dbdc025bSLars-Peter Clausen 448*dbdc025bSLars-Peter Clausen for (i = 0; i < st->chip_info->num_channels; ++i) { 449*dbdc025bSLars-Peter Clausen channels[i] = st->chip_info->channel_template; 450*dbdc025bSLars-Peter Clausen channels[i].channel = i; 451*dbdc025bSLars-Peter Clausen channels[i].address = AD5360_CHAN_ADDR(i); 452*dbdc025bSLars-Peter Clausen } 453*dbdc025bSLars-Peter Clausen 454*dbdc025bSLars-Peter Clausen indio_dev->channels = channels; 455*dbdc025bSLars-Peter Clausen 456*dbdc025bSLars-Peter Clausen return 0; 457*dbdc025bSLars-Peter Clausen } 458*dbdc025bSLars-Peter Clausen 459*dbdc025bSLars-Peter Clausen static int __devinit ad5360_probe(struct spi_device *spi) 460*dbdc025bSLars-Peter Clausen { 461*dbdc025bSLars-Peter Clausen enum ad5360_type type = spi_get_device_id(spi)->driver_data; 462*dbdc025bSLars-Peter Clausen struct iio_dev *indio_dev; 463*dbdc025bSLars-Peter Clausen struct ad5360_state *st; 464*dbdc025bSLars-Peter Clausen unsigned int i; 465*dbdc025bSLars-Peter Clausen int ret; 466*dbdc025bSLars-Peter Clausen 467*dbdc025bSLars-Peter Clausen indio_dev = iio_device_alloc(sizeof(*st)); 468*dbdc025bSLars-Peter Clausen if (indio_dev == NULL) { 469*dbdc025bSLars-Peter Clausen dev_err(&spi->dev, "Failed to allocate iio device\n"); 470*dbdc025bSLars-Peter Clausen return -ENOMEM; 471*dbdc025bSLars-Peter Clausen } 472*dbdc025bSLars-Peter Clausen 473*dbdc025bSLars-Peter Clausen st = iio_priv(indio_dev); 474*dbdc025bSLars-Peter Clausen spi_set_drvdata(spi, indio_dev); 475*dbdc025bSLars-Peter Clausen 476*dbdc025bSLars-Peter Clausen st->chip_info = &ad5360_chip_info_tbl[type]; 477*dbdc025bSLars-Peter Clausen st->spi = spi; 478*dbdc025bSLars-Peter Clausen 479*dbdc025bSLars-Peter Clausen indio_dev->dev.parent = &spi->dev; 480*dbdc025bSLars-Peter Clausen indio_dev->name = spi_get_device_id(spi)->name; 481*dbdc025bSLars-Peter Clausen indio_dev->info = &ad5360_info; 482*dbdc025bSLars-Peter Clausen indio_dev->modes = INDIO_DIRECT_MODE; 483*dbdc025bSLars-Peter Clausen indio_dev->num_channels = st->chip_info->num_channels; 484*dbdc025bSLars-Peter Clausen 485*dbdc025bSLars-Peter Clausen ret = ad5360_alloc_channels(indio_dev); 486*dbdc025bSLars-Peter Clausen if (ret) { 487*dbdc025bSLars-Peter Clausen dev_err(&spi->dev, "Failed to allocate channel spec: %d\n", ret); 488*dbdc025bSLars-Peter Clausen goto error_free; 489*dbdc025bSLars-Peter Clausen } 490*dbdc025bSLars-Peter Clausen 491*dbdc025bSLars-Peter Clausen for (i = 0; i < st->chip_info->num_vrefs; ++i) 492*dbdc025bSLars-Peter Clausen st->vref_reg[i].supply = ad5360_vref_name[i]; 493*dbdc025bSLars-Peter Clausen 494*dbdc025bSLars-Peter Clausen ret = regulator_bulk_get(&st->spi->dev, st->chip_info->num_vrefs, 495*dbdc025bSLars-Peter Clausen st->vref_reg); 496*dbdc025bSLars-Peter Clausen if (ret) { 497*dbdc025bSLars-Peter Clausen dev_err(&spi->dev, "Failed to request vref regulators: %d\n", ret); 498*dbdc025bSLars-Peter Clausen goto error_free_channels; 499*dbdc025bSLars-Peter Clausen } 500*dbdc025bSLars-Peter Clausen 501*dbdc025bSLars-Peter Clausen ret = regulator_bulk_enable(st->chip_info->num_vrefs, st->vref_reg); 502*dbdc025bSLars-Peter Clausen if (ret) { 503*dbdc025bSLars-Peter Clausen dev_err(&spi->dev, "Failed to enable vref regulators: %d\n", ret); 504*dbdc025bSLars-Peter Clausen goto error_free_reg; 505*dbdc025bSLars-Peter Clausen } 506*dbdc025bSLars-Peter Clausen 507*dbdc025bSLars-Peter Clausen ret = iio_device_register(indio_dev); 508*dbdc025bSLars-Peter Clausen if (ret) { 509*dbdc025bSLars-Peter Clausen dev_err(&spi->dev, "Failed to register iio device: %d\n", ret); 510*dbdc025bSLars-Peter Clausen goto error_disable_reg; 511*dbdc025bSLars-Peter Clausen } 512*dbdc025bSLars-Peter Clausen 513*dbdc025bSLars-Peter Clausen return 0; 514*dbdc025bSLars-Peter Clausen 515*dbdc025bSLars-Peter Clausen error_disable_reg: 516*dbdc025bSLars-Peter Clausen regulator_bulk_disable(st->chip_info->num_vrefs, st->vref_reg); 517*dbdc025bSLars-Peter Clausen error_free_reg: 518*dbdc025bSLars-Peter Clausen regulator_bulk_free(st->chip_info->num_vrefs, st->vref_reg); 519*dbdc025bSLars-Peter Clausen error_free_channels: 520*dbdc025bSLars-Peter Clausen kfree(indio_dev->channels); 521*dbdc025bSLars-Peter Clausen error_free: 522*dbdc025bSLars-Peter Clausen iio_device_free(indio_dev); 523*dbdc025bSLars-Peter Clausen 524*dbdc025bSLars-Peter Clausen return ret; 525*dbdc025bSLars-Peter Clausen } 526*dbdc025bSLars-Peter Clausen 527*dbdc025bSLars-Peter Clausen static int __devexit ad5360_remove(struct spi_device *spi) 528*dbdc025bSLars-Peter Clausen { 529*dbdc025bSLars-Peter Clausen struct iio_dev *indio_dev = spi_get_drvdata(spi); 530*dbdc025bSLars-Peter Clausen struct ad5360_state *st = iio_priv(indio_dev); 531*dbdc025bSLars-Peter Clausen 532*dbdc025bSLars-Peter Clausen iio_device_unregister(indio_dev); 533*dbdc025bSLars-Peter Clausen 534*dbdc025bSLars-Peter Clausen kfree(indio_dev->channels); 535*dbdc025bSLars-Peter Clausen 536*dbdc025bSLars-Peter Clausen regulator_bulk_disable(st->chip_info->num_vrefs, st->vref_reg); 537*dbdc025bSLars-Peter Clausen regulator_bulk_free(st->chip_info->num_vrefs, st->vref_reg); 538*dbdc025bSLars-Peter Clausen 539*dbdc025bSLars-Peter Clausen iio_device_free(indio_dev); 540*dbdc025bSLars-Peter Clausen 541*dbdc025bSLars-Peter Clausen return 0; 542*dbdc025bSLars-Peter Clausen } 543*dbdc025bSLars-Peter Clausen 544*dbdc025bSLars-Peter Clausen static const struct spi_device_id ad5360_ids[] = { 545*dbdc025bSLars-Peter Clausen { "ad5360", ID_AD5360 }, 546*dbdc025bSLars-Peter Clausen { "ad5361", ID_AD5361 }, 547*dbdc025bSLars-Peter Clausen { "ad5362", ID_AD5362 }, 548*dbdc025bSLars-Peter Clausen { "ad5363", ID_AD5363 }, 549*dbdc025bSLars-Peter Clausen { "ad5370", ID_AD5370 }, 550*dbdc025bSLars-Peter Clausen { "ad5371", ID_AD5371 }, 551*dbdc025bSLars-Peter Clausen { "ad5372", ID_AD5372 }, 552*dbdc025bSLars-Peter Clausen { "ad5373", ID_AD5373 }, 553*dbdc025bSLars-Peter Clausen {} 554*dbdc025bSLars-Peter Clausen }; 555*dbdc025bSLars-Peter Clausen MODULE_DEVICE_TABLE(spi, ad5360_ids); 556*dbdc025bSLars-Peter Clausen 557*dbdc025bSLars-Peter Clausen static struct spi_driver ad5360_driver = { 558*dbdc025bSLars-Peter Clausen .driver = { 559*dbdc025bSLars-Peter Clausen .name = "ad5360", 560*dbdc025bSLars-Peter Clausen .owner = THIS_MODULE, 561*dbdc025bSLars-Peter Clausen }, 562*dbdc025bSLars-Peter Clausen .probe = ad5360_probe, 563*dbdc025bSLars-Peter Clausen .remove = __devexit_p(ad5360_remove), 564*dbdc025bSLars-Peter Clausen .id_table = ad5360_ids, 565*dbdc025bSLars-Peter Clausen }; 566*dbdc025bSLars-Peter Clausen module_spi_driver(ad5360_driver); 567*dbdc025bSLars-Peter Clausen 568*dbdc025bSLars-Peter Clausen MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 569*dbdc025bSLars-Peter Clausen MODULE_DESCRIPTION("Analog Devices AD5360/61/62/63/70/71/72/73 DAC"); 570*dbdc025bSLars-Peter Clausen MODULE_LICENSE("GPL v2"); 571