1*dbdc025bSLars-Peter Clausen /* 2*dbdc025bSLars-Peter Clausen * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5648, 3*dbdc025bSLars-Peter Clausen * AD5666, AD5668 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 AD5064_MAX_DAC_CHANNELS 8 23*dbdc025bSLars-Peter Clausen #define AD5064_MAX_VREFS 4 24*dbdc025bSLars-Peter Clausen 25*dbdc025bSLars-Peter Clausen #define AD5064_ADDR(x) ((x) << 20) 26*dbdc025bSLars-Peter Clausen #define AD5064_CMD(x) ((x) << 24) 27*dbdc025bSLars-Peter Clausen 28*dbdc025bSLars-Peter Clausen #define AD5064_ADDR_DAC(chan) (chan) 29*dbdc025bSLars-Peter Clausen #define AD5064_ADDR_ALL_DAC 0xF 30*dbdc025bSLars-Peter Clausen 31*dbdc025bSLars-Peter Clausen #define AD5064_CMD_WRITE_INPUT_N 0x0 32*dbdc025bSLars-Peter Clausen #define AD5064_CMD_UPDATE_DAC_N 0x1 33*dbdc025bSLars-Peter Clausen #define AD5064_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2 34*dbdc025bSLars-Peter Clausen #define AD5064_CMD_WRITE_INPUT_N_UPDATE_N 0x3 35*dbdc025bSLars-Peter Clausen #define AD5064_CMD_POWERDOWN_DAC 0x4 36*dbdc025bSLars-Peter Clausen #define AD5064_CMD_CLEAR 0x5 37*dbdc025bSLars-Peter Clausen #define AD5064_CMD_LDAC_MASK 0x6 38*dbdc025bSLars-Peter Clausen #define AD5064_CMD_RESET 0x7 39*dbdc025bSLars-Peter Clausen #define AD5064_CMD_CONFIG 0x8 40*dbdc025bSLars-Peter Clausen 41*dbdc025bSLars-Peter Clausen #define AD5064_CONFIG_DAISY_CHAIN_ENABLE BIT(1) 42*dbdc025bSLars-Peter Clausen #define AD5064_CONFIG_INT_VREF_ENABLE BIT(0) 43*dbdc025bSLars-Peter Clausen 44*dbdc025bSLars-Peter Clausen #define AD5064_LDAC_PWRDN_NONE 0x0 45*dbdc025bSLars-Peter Clausen #define AD5064_LDAC_PWRDN_1K 0x1 46*dbdc025bSLars-Peter Clausen #define AD5064_LDAC_PWRDN_100K 0x2 47*dbdc025bSLars-Peter Clausen #define AD5064_LDAC_PWRDN_3STATE 0x3 48*dbdc025bSLars-Peter Clausen 49*dbdc025bSLars-Peter Clausen /** 50*dbdc025bSLars-Peter Clausen * struct ad5064_chip_info - chip specific information 51*dbdc025bSLars-Peter Clausen * @shared_vref: whether the vref supply is shared between channels 52*dbdc025bSLars-Peter Clausen * @internal_vref: internal reference voltage. 0 if the chip has no internal 53*dbdc025bSLars-Peter Clausen * vref. 54*dbdc025bSLars-Peter Clausen * @channel: channel specification 55*dbdc025bSLars-Peter Clausen * @num_channels: number of channels 56*dbdc025bSLars-Peter Clausen */ 57*dbdc025bSLars-Peter Clausen 58*dbdc025bSLars-Peter Clausen struct ad5064_chip_info { 59*dbdc025bSLars-Peter Clausen bool shared_vref; 60*dbdc025bSLars-Peter Clausen unsigned long internal_vref; 61*dbdc025bSLars-Peter Clausen const struct iio_chan_spec *channels; 62*dbdc025bSLars-Peter Clausen unsigned int num_channels; 63*dbdc025bSLars-Peter Clausen }; 64*dbdc025bSLars-Peter Clausen 65*dbdc025bSLars-Peter Clausen /** 66*dbdc025bSLars-Peter Clausen * struct ad5064_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 * @pwr_down: whether channel is powered down 71*dbdc025bSLars-Peter Clausen * @pwr_down_mode: channel's current power down mode 72*dbdc025bSLars-Peter Clausen * @dac_cache: current DAC raw value (chip does not support readback) 73*dbdc025bSLars-Peter Clausen * @use_internal_vref: set to true if the internal reference voltage should be 74*dbdc025bSLars-Peter Clausen * used. 75*dbdc025bSLars-Peter Clausen * @data: spi transfer buffers 76*dbdc025bSLars-Peter Clausen */ 77*dbdc025bSLars-Peter Clausen 78*dbdc025bSLars-Peter Clausen struct ad5064_state { 79*dbdc025bSLars-Peter Clausen struct spi_device *spi; 80*dbdc025bSLars-Peter Clausen const struct ad5064_chip_info *chip_info; 81*dbdc025bSLars-Peter Clausen struct regulator_bulk_data vref_reg[AD5064_MAX_VREFS]; 82*dbdc025bSLars-Peter Clausen bool pwr_down[AD5064_MAX_DAC_CHANNELS]; 83*dbdc025bSLars-Peter Clausen u8 pwr_down_mode[AD5064_MAX_DAC_CHANNELS]; 84*dbdc025bSLars-Peter Clausen unsigned int dac_cache[AD5064_MAX_DAC_CHANNELS]; 85*dbdc025bSLars-Peter Clausen bool use_internal_vref; 86*dbdc025bSLars-Peter Clausen 87*dbdc025bSLars-Peter Clausen /* 88*dbdc025bSLars-Peter Clausen * DMA (thus cache coherency maintenance) requires the 89*dbdc025bSLars-Peter Clausen * transfer buffers to live in their own cache lines. 90*dbdc025bSLars-Peter Clausen */ 91*dbdc025bSLars-Peter Clausen __be32 data ____cacheline_aligned; 92*dbdc025bSLars-Peter Clausen }; 93*dbdc025bSLars-Peter Clausen 94*dbdc025bSLars-Peter Clausen enum ad5064_type { 95*dbdc025bSLars-Peter Clausen ID_AD5024, 96*dbdc025bSLars-Peter Clausen ID_AD5025, 97*dbdc025bSLars-Peter Clausen ID_AD5044, 98*dbdc025bSLars-Peter Clausen ID_AD5045, 99*dbdc025bSLars-Peter Clausen ID_AD5064, 100*dbdc025bSLars-Peter Clausen ID_AD5064_1, 101*dbdc025bSLars-Peter Clausen ID_AD5065, 102*dbdc025bSLars-Peter Clausen ID_AD5628_1, 103*dbdc025bSLars-Peter Clausen ID_AD5628_2, 104*dbdc025bSLars-Peter Clausen ID_AD5648_1, 105*dbdc025bSLars-Peter Clausen ID_AD5648_2, 106*dbdc025bSLars-Peter Clausen ID_AD5666_1, 107*dbdc025bSLars-Peter Clausen ID_AD5666_2, 108*dbdc025bSLars-Peter Clausen ID_AD5668_1, 109*dbdc025bSLars-Peter Clausen ID_AD5668_2, 110*dbdc025bSLars-Peter Clausen }; 111*dbdc025bSLars-Peter Clausen 112*dbdc025bSLars-Peter Clausen static int ad5064_spi_write(struct ad5064_state *st, unsigned int cmd, 113*dbdc025bSLars-Peter Clausen unsigned int addr, unsigned int val, unsigned int shift) 114*dbdc025bSLars-Peter Clausen { 115*dbdc025bSLars-Peter Clausen val <<= shift; 116*dbdc025bSLars-Peter Clausen 117*dbdc025bSLars-Peter Clausen st->data = cpu_to_be32(AD5064_CMD(cmd) | AD5064_ADDR(addr) | val); 118*dbdc025bSLars-Peter Clausen 119*dbdc025bSLars-Peter Clausen return spi_write(st->spi, &st->data, sizeof(st->data)); 120*dbdc025bSLars-Peter Clausen } 121*dbdc025bSLars-Peter Clausen 122*dbdc025bSLars-Peter Clausen static int ad5064_sync_powerdown_mode(struct ad5064_state *st, 123*dbdc025bSLars-Peter Clausen unsigned int channel) 124*dbdc025bSLars-Peter Clausen { 125*dbdc025bSLars-Peter Clausen unsigned int val; 126*dbdc025bSLars-Peter Clausen int ret; 127*dbdc025bSLars-Peter Clausen 128*dbdc025bSLars-Peter Clausen val = (0x1 << channel); 129*dbdc025bSLars-Peter Clausen 130*dbdc025bSLars-Peter Clausen if (st->pwr_down[channel]) 131*dbdc025bSLars-Peter Clausen val |= st->pwr_down_mode[channel] << 8; 132*dbdc025bSLars-Peter Clausen 133*dbdc025bSLars-Peter Clausen ret = ad5064_spi_write(st, AD5064_CMD_POWERDOWN_DAC, 0, val, 0); 134*dbdc025bSLars-Peter Clausen 135*dbdc025bSLars-Peter Clausen return ret; 136*dbdc025bSLars-Peter Clausen } 137*dbdc025bSLars-Peter Clausen 138*dbdc025bSLars-Peter Clausen static const char * const ad5064_powerdown_modes[] = { 139*dbdc025bSLars-Peter Clausen "1kohm_to_gnd", 140*dbdc025bSLars-Peter Clausen "100kohm_to_gnd", 141*dbdc025bSLars-Peter Clausen "three_state", 142*dbdc025bSLars-Peter Clausen }; 143*dbdc025bSLars-Peter Clausen 144*dbdc025bSLars-Peter Clausen static int ad5064_get_powerdown_mode(struct iio_dev *indio_dev, 145*dbdc025bSLars-Peter Clausen const struct iio_chan_spec *chan) 146*dbdc025bSLars-Peter Clausen { 147*dbdc025bSLars-Peter Clausen struct ad5064_state *st = iio_priv(indio_dev); 148*dbdc025bSLars-Peter Clausen 149*dbdc025bSLars-Peter Clausen return st->pwr_down_mode[chan->channel] - 1; 150*dbdc025bSLars-Peter Clausen } 151*dbdc025bSLars-Peter Clausen 152*dbdc025bSLars-Peter Clausen static int ad5064_set_powerdown_mode(struct iio_dev *indio_dev, 153*dbdc025bSLars-Peter Clausen const struct iio_chan_spec *chan, unsigned int mode) 154*dbdc025bSLars-Peter Clausen { 155*dbdc025bSLars-Peter Clausen struct ad5064_state *st = iio_priv(indio_dev); 156*dbdc025bSLars-Peter Clausen int ret; 157*dbdc025bSLars-Peter Clausen 158*dbdc025bSLars-Peter Clausen mutex_lock(&indio_dev->mlock); 159*dbdc025bSLars-Peter Clausen st->pwr_down_mode[chan->channel] = mode + 1; 160*dbdc025bSLars-Peter Clausen 161*dbdc025bSLars-Peter Clausen ret = ad5064_sync_powerdown_mode(st, chan->channel); 162*dbdc025bSLars-Peter Clausen mutex_unlock(&indio_dev->mlock); 163*dbdc025bSLars-Peter Clausen 164*dbdc025bSLars-Peter Clausen return ret; 165*dbdc025bSLars-Peter Clausen } 166*dbdc025bSLars-Peter Clausen 167*dbdc025bSLars-Peter Clausen static const struct iio_enum ad5064_powerdown_mode_enum = { 168*dbdc025bSLars-Peter Clausen .items = ad5064_powerdown_modes, 169*dbdc025bSLars-Peter Clausen .num_items = ARRAY_SIZE(ad5064_powerdown_modes), 170*dbdc025bSLars-Peter Clausen .get = ad5064_get_powerdown_mode, 171*dbdc025bSLars-Peter Clausen .set = ad5064_set_powerdown_mode, 172*dbdc025bSLars-Peter Clausen }; 173*dbdc025bSLars-Peter Clausen 174*dbdc025bSLars-Peter Clausen static ssize_t ad5064_read_dac_powerdown(struct iio_dev *indio_dev, 175*dbdc025bSLars-Peter Clausen uintptr_t private, const struct iio_chan_spec *chan, char *buf) 176*dbdc025bSLars-Peter Clausen { 177*dbdc025bSLars-Peter Clausen struct ad5064_state *st = iio_priv(indio_dev); 178*dbdc025bSLars-Peter Clausen 179*dbdc025bSLars-Peter Clausen return sprintf(buf, "%d\n", st->pwr_down[chan->channel]); 180*dbdc025bSLars-Peter Clausen } 181*dbdc025bSLars-Peter Clausen 182*dbdc025bSLars-Peter Clausen static ssize_t ad5064_write_dac_powerdown(struct iio_dev *indio_dev, 183*dbdc025bSLars-Peter Clausen uintptr_t private, const struct iio_chan_spec *chan, const char *buf, 184*dbdc025bSLars-Peter Clausen size_t len) 185*dbdc025bSLars-Peter Clausen { 186*dbdc025bSLars-Peter Clausen struct ad5064_state *st = iio_priv(indio_dev); 187*dbdc025bSLars-Peter Clausen bool pwr_down; 188*dbdc025bSLars-Peter Clausen int ret; 189*dbdc025bSLars-Peter Clausen 190*dbdc025bSLars-Peter Clausen ret = strtobool(buf, &pwr_down); 191*dbdc025bSLars-Peter Clausen if (ret) 192*dbdc025bSLars-Peter Clausen return ret; 193*dbdc025bSLars-Peter Clausen 194*dbdc025bSLars-Peter Clausen mutex_lock(&indio_dev->mlock); 195*dbdc025bSLars-Peter Clausen st->pwr_down[chan->channel] = pwr_down; 196*dbdc025bSLars-Peter Clausen 197*dbdc025bSLars-Peter Clausen ret = ad5064_sync_powerdown_mode(st, chan->channel); 198*dbdc025bSLars-Peter Clausen mutex_unlock(&indio_dev->mlock); 199*dbdc025bSLars-Peter Clausen return ret ? ret : len; 200*dbdc025bSLars-Peter Clausen } 201*dbdc025bSLars-Peter Clausen 202*dbdc025bSLars-Peter Clausen static int ad5064_get_vref(struct ad5064_state *st, 203*dbdc025bSLars-Peter Clausen struct iio_chan_spec const *chan) 204*dbdc025bSLars-Peter Clausen { 205*dbdc025bSLars-Peter Clausen unsigned int i; 206*dbdc025bSLars-Peter Clausen 207*dbdc025bSLars-Peter Clausen if (st->use_internal_vref) 208*dbdc025bSLars-Peter Clausen return st->chip_info->internal_vref; 209*dbdc025bSLars-Peter Clausen 210*dbdc025bSLars-Peter Clausen i = st->chip_info->shared_vref ? 0 : chan->channel; 211*dbdc025bSLars-Peter Clausen return regulator_get_voltage(st->vref_reg[i].consumer); 212*dbdc025bSLars-Peter Clausen } 213*dbdc025bSLars-Peter Clausen 214*dbdc025bSLars-Peter Clausen static int ad5064_read_raw(struct iio_dev *indio_dev, 215*dbdc025bSLars-Peter Clausen struct iio_chan_spec const *chan, 216*dbdc025bSLars-Peter Clausen int *val, 217*dbdc025bSLars-Peter Clausen int *val2, 218*dbdc025bSLars-Peter Clausen long m) 219*dbdc025bSLars-Peter Clausen { 220*dbdc025bSLars-Peter Clausen struct ad5064_state *st = iio_priv(indio_dev); 221*dbdc025bSLars-Peter Clausen int scale_uv; 222*dbdc025bSLars-Peter Clausen 223*dbdc025bSLars-Peter Clausen switch (m) { 224*dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_RAW: 225*dbdc025bSLars-Peter Clausen *val = st->dac_cache[chan->channel]; 226*dbdc025bSLars-Peter Clausen return IIO_VAL_INT; 227*dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_SCALE: 228*dbdc025bSLars-Peter Clausen scale_uv = ad5064_get_vref(st, chan); 229*dbdc025bSLars-Peter Clausen if (scale_uv < 0) 230*dbdc025bSLars-Peter Clausen return scale_uv; 231*dbdc025bSLars-Peter Clausen 232*dbdc025bSLars-Peter Clausen scale_uv = (scale_uv * 100) >> chan->scan_type.realbits; 233*dbdc025bSLars-Peter Clausen *val = scale_uv / 100000; 234*dbdc025bSLars-Peter Clausen *val2 = (scale_uv % 100000) * 10; 235*dbdc025bSLars-Peter Clausen return IIO_VAL_INT_PLUS_MICRO; 236*dbdc025bSLars-Peter Clausen default: 237*dbdc025bSLars-Peter Clausen break; 238*dbdc025bSLars-Peter Clausen } 239*dbdc025bSLars-Peter Clausen return -EINVAL; 240*dbdc025bSLars-Peter Clausen } 241*dbdc025bSLars-Peter Clausen 242*dbdc025bSLars-Peter Clausen static int ad5064_write_raw(struct iio_dev *indio_dev, 243*dbdc025bSLars-Peter Clausen struct iio_chan_spec const *chan, int val, int val2, long mask) 244*dbdc025bSLars-Peter Clausen { 245*dbdc025bSLars-Peter Clausen struct ad5064_state *st = iio_priv(indio_dev); 246*dbdc025bSLars-Peter Clausen int ret; 247*dbdc025bSLars-Peter Clausen 248*dbdc025bSLars-Peter Clausen switch (mask) { 249*dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_RAW: 250*dbdc025bSLars-Peter Clausen if (val > (1 << chan->scan_type.realbits) || val < 0) 251*dbdc025bSLars-Peter Clausen return -EINVAL; 252*dbdc025bSLars-Peter Clausen 253*dbdc025bSLars-Peter Clausen mutex_lock(&indio_dev->mlock); 254*dbdc025bSLars-Peter Clausen ret = ad5064_spi_write(st, AD5064_CMD_WRITE_INPUT_N_UPDATE_N, 255*dbdc025bSLars-Peter Clausen chan->address, val, chan->scan_type.shift); 256*dbdc025bSLars-Peter Clausen if (ret == 0) 257*dbdc025bSLars-Peter Clausen st->dac_cache[chan->channel] = val; 258*dbdc025bSLars-Peter Clausen mutex_unlock(&indio_dev->mlock); 259*dbdc025bSLars-Peter Clausen break; 260*dbdc025bSLars-Peter Clausen default: 261*dbdc025bSLars-Peter Clausen ret = -EINVAL; 262*dbdc025bSLars-Peter Clausen } 263*dbdc025bSLars-Peter Clausen 264*dbdc025bSLars-Peter Clausen return ret; 265*dbdc025bSLars-Peter Clausen } 266*dbdc025bSLars-Peter Clausen 267*dbdc025bSLars-Peter Clausen static const struct iio_info ad5064_info = { 268*dbdc025bSLars-Peter Clausen .read_raw = ad5064_read_raw, 269*dbdc025bSLars-Peter Clausen .write_raw = ad5064_write_raw, 270*dbdc025bSLars-Peter Clausen .driver_module = THIS_MODULE, 271*dbdc025bSLars-Peter Clausen }; 272*dbdc025bSLars-Peter Clausen 273*dbdc025bSLars-Peter Clausen static const struct iio_chan_spec_ext_info ad5064_ext_info[] = { 274*dbdc025bSLars-Peter Clausen { 275*dbdc025bSLars-Peter Clausen .name = "powerdown", 276*dbdc025bSLars-Peter Clausen .read = ad5064_read_dac_powerdown, 277*dbdc025bSLars-Peter Clausen .write = ad5064_write_dac_powerdown, 278*dbdc025bSLars-Peter Clausen }, 279*dbdc025bSLars-Peter Clausen IIO_ENUM("powerdown_mode", false, &ad5064_powerdown_mode_enum), 280*dbdc025bSLars-Peter Clausen IIO_ENUM_AVAILABLE("powerdown_mode", &ad5064_powerdown_mode_enum), 281*dbdc025bSLars-Peter Clausen { }, 282*dbdc025bSLars-Peter Clausen }; 283*dbdc025bSLars-Peter Clausen 284*dbdc025bSLars-Peter Clausen #define AD5064_CHANNEL(chan, bits) { \ 285*dbdc025bSLars-Peter Clausen .type = IIO_VOLTAGE, \ 286*dbdc025bSLars-Peter Clausen .indexed = 1, \ 287*dbdc025bSLars-Peter Clausen .output = 1, \ 288*dbdc025bSLars-Peter Clausen .channel = (chan), \ 289*dbdc025bSLars-Peter Clausen .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ 290*dbdc025bSLars-Peter Clausen IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ 291*dbdc025bSLars-Peter Clausen .address = AD5064_ADDR_DAC(chan), \ 292*dbdc025bSLars-Peter Clausen .scan_type = IIO_ST('u', (bits), 16, 20 - (bits)), \ 293*dbdc025bSLars-Peter Clausen .ext_info = ad5064_ext_info, \ 294*dbdc025bSLars-Peter Clausen } 295*dbdc025bSLars-Peter Clausen 296*dbdc025bSLars-Peter Clausen #define DECLARE_AD5064_CHANNELS(name, bits) \ 297*dbdc025bSLars-Peter Clausen const struct iio_chan_spec name[] = { \ 298*dbdc025bSLars-Peter Clausen AD5064_CHANNEL(0, bits), \ 299*dbdc025bSLars-Peter Clausen AD5064_CHANNEL(1, bits), \ 300*dbdc025bSLars-Peter Clausen AD5064_CHANNEL(2, bits), \ 301*dbdc025bSLars-Peter Clausen AD5064_CHANNEL(3, bits), \ 302*dbdc025bSLars-Peter Clausen AD5064_CHANNEL(4, bits), \ 303*dbdc025bSLars-Peter Clausen AD5064_CHANNEL(5, bits), \ 304*dbdc025bSLars-Peter Clausen AD5064_CHANNEL(6, bits), \ 305*dbdc025bSLars-Peter Clausen AD5064_CHANNEL(7, bits), \ 306*dbdc025bSLars-Peter Clausen } 307*dbdc025bSLars-Peter Clausen 308*dbdc025bSLars-Peter Clausen static DECLARE_AD5064_CHANNELS(ad5024_channels, 12); 309*dbdc025bSLars-Peter Clausen static DECLARE_AD5064_CHANNELS(ad5044_channels, 14); 310*dbdc025bSLars-Peter Clausen static DECLARE_AD5064_CHANNELS(ad5064_channels, 16); 311*dbdc025bSLars-Peter Clausen 312*dbdc025bSLars-Peter Clausen static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { 313*dbdc025bSLars-Peter Clausen [ID_AD5024] = { 314*dbdc025bSLars-Peter Clausen .shared_vref = false, 315*dbdc025bSLars-Peter Clausen .channels = ad5024_channels, 316*dbdc025bSLars-Peter Clausen .num_channels = 4, 317*dbdc025bSLars-Peter Clausen }, 318*dbdc025bSLars-Peter Clausen [ID_AD5025] = { 319*dbdc025bSLars-Peter Clausen .shared_vref = false, 320*dbdc025bSLars-Peter Clausen .channels = ad5024_channels, 321*dbdc025bSLars-Peter Clausen .num_channels = 2, 322*dbdc025bSLars-Peter Clausen }, 323*dbdc025bSLars-Peter Clausen [ID_AD5044] = { 324*dbdc025bSLars-Peter Clausen .shared_vref = false, 325*dbdc025bSLars-Peter Clausen .channels = ad5044_channels, 326*dbdc025bSLars-Peter Clausen .num_channels = 4, 327*dbdc025bSLars-Peter Clausen }, 328*dbdc025bSLars-Peter Clausen [ID_AD5045] = { 329*dbdc025bSLars-Peter Clausen .shared_vref = false, 330*dbdc025bSLars-Peter Clausen .channels = ad5044_channels, 331*dbdc025bSLars-Peter Clausen .num_channels = 2, 332*dbdc025bSLars-Peter Clausen }, 333*dbdc025bSLars-Peter Clausen [ID_AD5064] = { 334*dbdc025bSLars-Peter Clausen .shared_vref = false, 335*dbdc025bSLars-Peter Clausen .channels = ad5064_channels, 336*dbdc025bSLars-Peter Clausen .num_channels = 4, 337*dbdc025bSLars-Peter Clausen }, 338*dbdc025bSLars-Peter Clausen [ID_AD5064_1] = { 339*dbdc025bSLars-Peter Clausen .shared_vref = true, 340*dbdc025bSLars-Peter Clausen .channels = ad5064_channels, 341*dbdc025bSLars-Peter Clausen .num_channels = 4, 342*dbdc025bSLars-Peter Clausen }, 343*dbdc025bSLars-Peter Clausen [ID_AD5065] = { 344*dbdc025bSLars-Peter Clausen .shared_vref = false, 345*dbdc025bSLars-Peter Clausen .channels = ad5064_channels, 346*dbdc025bSLars-Peter Clausen .num_channels = 2, 347*dbdc025bSLars-Peter Clausen }, 348*dbdc025bSLars-Peter Clausen [ID_AD5628_1] = { 349*dbdc025bSLars-Peter Clausen .shared_vref = true, 350*dbdc025bSLars-Peter Clausen .internal_vref = 2500000, 351*dbdc025bSLars-Peter Clausen .channels = ad5024_channels, 352*dbdc025bSLars-Peter Clausen .num_channels = 8, 353*dbdc025bSLars-Peter Clausen }, 354*dbdc025bSLars-Peter Clausen [ID_AD5628_2] = { 355*dbdc025bSLars-Peter Clausen .shared_vref = true, 356*dbdc025bSLars-Peter Clausen .internal_vref = 5000000, 357*dbdc025bSLars-Peter Clausen .channels = ad5024_channels, 358*dbdc025bSLars-Peter Clausen .num_channels = 8, 359*dbdc025bSLars-Peter Clausen }, 360*dbdc025bSLars-Peter Clausen [ID_AD5648_1] = { 361*dbdc025bSLars-Peter Clausen .shared_vref = true, 362*dbdc025bSLars-Peter Clausen .internal_vref = 2500000, 363*dbdc025bSLars-Peter Clausen .channels = ad5044_channels, 364*dbdc025bSLars-Peter Clausen .num_channels = 8, 365*dbdc025bSLars-Peter Clausen }, 366*dbdc025bSLars-Peter Clausen [ID_AD5648_2] = { 367*dbdc025bSLars-Peter Clausen .shared_vref = true, 368*dbdc025bSLars-Peter Clausen .internal_vref = 5000000, 369*dbdc025bSLars-Peter Clausen .channels = ad5044_channels, 370*dbdc025bSLars-Peter Clausen .num_channels = 8, 371*dbdc025bSLars-Peter Clausen }, 372*dbdc025bSLars-Peter Clausen [ID_AD5666_1] = { 373*dbdc025bSLars-Peter Clausen .shared_vref = true, 374*dbdc025bSLars-Peter Clausen .internal_vref = 2500000, 375*dbdc025bSLars-Peter Clausen .channels = ad5064_channels, 376*dbdc025bSLars-Peter Clausen .num_channels = 4, 377*dbdc025bSLars-Peter Clausen }, 378*dbdc025bSLars-Peter Clausen [ID_AD5666_2] = { 379*dbdc025bSLars-Peter Clausen .shared_vref = true, 380*dbdc025bSLars-Peter Clausen .internal_vref = 5000000, 381*dbdc025bSLars-Peter Clausen .channels = ad5064_channels, 382*dbdc025bSLars-Peter Clausen .num_channels = 4, 383*dbdc025bSLars-Peter Clausen }, 384*dbdc025bSLars-Peter Clausen [ID_AD5668_1] = { 385*dbdc025bSLars-Peter Clausen .shared_vref = true, 386*dbdc025bSLars-Peter Clausen .internal_vref = 2500000, 387*dbdc025bSLars-Peter Clausen .channels = ad5064_channels, 388*dbdc025bSLars-Peter Clausen .num_channels = 8, 389*dbdc025bSLars-Peter Clausen }, 390*dbdc025bSLars-Peter Clausen [ID_AD5668_2] = { 391*dbdc025bSLars-Peter Clausen .shared_vref = true, 392*dbdc025bSLars-Peter Clausen .internal_vref = 5000000, 393*dbdc025bSLars-Peter Clausen .channels = ad5064_channels, 394*dbdc025bSLars-Peter Clausen .num_channels = 8, 395*dbdc025bSLars-Peter Clausen }, 396*dbdc025bSLars-Peter Clausen }; 397*dbdc025bSLars-Peter Clausen 398*dbdc025bSLars-Peter Clausen static inline unsigned int ad5064_num_vref(struct ad5064_state *st) 399*dbdc025bSLars-Peter Clausen { 400*dbdc025bSLars-Peter Clausen return st->chip_info->shared_vref ? 1 : st->chip_info->num_channels; 401*dbdc025bSLars-Peter Clausen } 402*dbdc025bSLars-Peter Clausen 403*dbdc025bSLars-Peter Clausen static const char * const ad5064_vref_names[] = { 404*dbdc025bSLars-Peter Clausen "vrefA", 405*dbdc025bSLars-Peter Clausen "vrefB", 406*dbdc025bSLars-Peter Clausen "vrefC", 407*dbdc025bSLars-Peter Clausen "vrefD", 408*dbdc025bSLars-Peter Clausen }; 409*dbdc025bSLars-Peter Clausen 410*dbdc025bSLars-Peter Clausen static const char * const ad5064_vref_name(struct ad5064_state *st, 411*dbdc025bSLars-Peter Clausen unsigned int vref) 412*dbdc025bSLars-Peter Clausen { 413*dbdc025bSLars-Peter Clausen return st->chip_info->shared_vref ? "vref" : ad5064_vref_names[vref]; 414*dbdc025bSLars-Peter Clausen } 415*dbdc025bSLars-Peter Clausen 416*dbdc025bSLars-Peter Clausen static int __devinit ad5064_probe(struct spi_device *spi) 417*dbdc025bSLars-Peter Clausen { 418*dbdc025bSLars-Peter Clausen enum ad5064_type type = spi_get_device_id(spi)->driver_data; 419*dbdc025bSLars-Peter Clausen struct iio_dev *indio_dev; 420*dbdc025bSLars-Peter Clausen struct ad5064_state *st; 421*dbdc025bSLars-Peter Clausen unsigned int i; 422*dbdc025bSLars-Peter Clausen int ret; 423*dbdc025bSLars-Peter Clausen 424*dbdc025bSLars-Peter Clausen indio_dev = iio_device_alloc(sizeof(*st)); 425*dbdc025bSLars-Peter Clausen if (indio_dev == NULL) 426*dbdc025bSLars-Peter Clausen return -ENOMEM; 427*dbdc025bSLars-Peter Clausen 428*dbdc025bSLars-Peter Clausen st = iio_priv(indio_dev); 429*dbdc025bSLars-Peter Clausen spi_set_drvdata(spi, indio_dev); 430*dbdc025bSLars-Peter Clausen 431*dbdc025bSLars-Peter Clausen st->chip_info = &ad5064_chip_info_tbl[type]; 432*dbdc025bSLars-Peter Clausen st->spi = spi; 433*dbdc025bSLars-Peter Clausen 434*dbdc025bSLars-Peter Clausen for (i = 0; i < ad5064_num_vref(st); ++i) 435*dbdc025bSLars-Peter Clausen st->vref_reg[i].supply = ad5064_vref_name(st, i); 436*dbdc025bSLars-Peter Clausen 437*dbdc025bSLars-Peter Clausen ret = regulator_bulk_get(&st->spi->dev, ad5064_num_vref(st), 438*dbdc025bSLars-Peter Clausen st->vref_reg); 439*dbdc025bSLars-Peter Clausen if (ret) { 440*dbdc025bSLars-Peter Clausen if (!st->chip_info->internal_vref) 441*dbdc025bSLars-Peter Clausen goto error_free; 442*dbdc025bSLars-Peter Clausen st->use_internal_vref = true; 443*dbdc025bSLars-Peter Clausen ret = ad5064_spi_write(st, AD5064_CMD_CONFIG, 0, 444*dbdc025bSLars-Peter Clausen AD5064_CONFIG_INT_VREF_ENABLE, 0); 445*dbdc025bSLars-Peter Clausen if (ret) { 446*dbdc025bSLars-Peter Clausen dev_err(&spi->dev, "Failed to enable internal vref: %d\n", 447*dbdc025bSLars-Peter Clausen ret); 448*dbdc025bSLars-Peter Clausen goto error_free; 449*dbdc025bSLars-Peter Clausen } 450*dbdc025bSLars-Peter Clausen } else { 451*dbdc025bSLars-Peter Clausen ret = regulator_bulk_enable(ad5064_num_vref(st), st->vref_reg); 452*dbdc025bSLars-Peter Clausen if (ret) 453*dbdc025bSLars-Peter Clausen goto error_free_reg; 454*dbdc025bSLars-Peter Clausen } 455*dbdc025bSLars-Peter Clausen 456*dbdc025bSLars-Peter Clausen for (i = 0; i < st->chip_info->num_channels; ++i) { 457*dbdc025bSLars-Peter Clausen st->pwr_down_mode[i] = AD5064_LDAC_PWRDN_1K; 458*dbdc025bSLars-Peter Clausen st->dac_cache[i] = 0x8000; 459*dbdc025bSLars-Peter Clausen } 460*dbdc025bSLars-Peter Clausen 461*dbdc025bSLars-Peter Clausen indio_dev->dev.parent = &spi->dev; 462*dbdc025bSLars-Peter Clausen indio_dev->name = spi_get_device_id(spi)->name; 463*dbdc025bSLars-Peter Clausen indio_dev->info = &ad5064_info; 464*dbdc025bSLars-Peter Clausen indio_dev->modes = INDIO_DIRECT_MODE; 465*dbdc025bSLars-Peter Clausen indio_dev->channels = st->chip_info->channels; 466*dbdc025bSLars-Peter Clausen indio_dev->num_channels = st->chip_info->num_channels; 467*dbdc025bSLars-Peter Clausen 468*dbdc025bSLars-Peter Clausen ret = iio_device_register(indio_dev); 469*dbdc025bSLars-Peter Clausen if (ret) 470*dbdc025bSLars-Peter Clausen goto error_disable_reg; 471*dbdc025bSLars-Peter Clausen 472*dbdc025bSLars-Peter Clausen return 0; 473*dbdc025bSLars-Peter Clausen 474*dbdc025bSLars-Peter Clausen error_disable_reg: 475*dbdc025bSLars-Peter Clausen if (!st->use_internal_vref) 476*dbdc025bSLars-Peter Clausen regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); 477*dbdc025bSLars-Peter Clausen error_free_reg: 478*dbdc025bSLars-Peter Clausen if (!st->use_internal_vref) 479*dbdc025bSLars-Peter Clausen regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); 480*dbdc025bSLars-Peter Clausen error_free: 481*dbdc025bSLars-Peter Clausen iio_device_free(indio_dev); 482*dbdc025bSLars-Peter Clausen 483*dbdc025bSLars-Peter Clausen return ret; 484*dbdc025bSLars-Peter Clausen } 485*dbdc025bSLars-Peter Clausen 486*dbdc025bSLars-Peter Clausen 487*dbdc025bSLars-Peter Clausen static int __devexit ad5064_remove(struct spi_device *spi) 488*dbdc025bSLars-Peter Clausen { 489*dbdc025bSLars-Peter Clausen struct iio_dev *indio_dev = spi_get_drvdata(spi); 490*dbdc025bSLars-Peter Clausen struct ad5064_state *st = iio_priv(indio_dev); 491*dbdc025bSLars-Peter Clausen 492*dbdc025bSLars-Peter Clausen iio_device_unregister(indio_dev); 493*dbdc025bSLars-Peter Clausen 494*dbdc025bSLars-Peter Clausen if (!st->use_internal_vref) { 495*dbdc025bSLars-Peter Clausen regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); 496*dbdc025bSLars-Peter Clausen regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); 497*dbdc025bSLars-Peter Clausen } 498*dbdc025bSLars-Peter Clausen 499*dbdc025bSLars-Peter Clausen iio_device_free(indio_dev); 500*dbdc025bSLars-Peter Clausen 501*dbdc025bSLars-Peter Clausen return 0; 502*dbdc025bSLars-Peter Clausen } 503*dbdc025bSLars-Peter Clausen 504*dbdc025bSLars-Peter Clausen static const struct spi_device_id ad5064_id[] = { 505*dbdc025bSLars-Peter Clausen {"ad5024", ID_AD5024}, 506*dbdc025bSLars-Peter Clausen {"ad5025", ID_AD5025}, 507*dbdc025bSLars-Peter Clausen {"ad5044", ID_AD5044}, 508*dbdc025bSLars-Peter Clausen {"ad5045", ID_AD5045}, 509*dbdc025bSLars-Peter Clausen {"ad5064", ID_AD5064}, 510*dbdc025bSLars-Peter Clausen {"ad5064-1", ID_AD5064_1}, 511*dbdc025bSLars-Peter Clausen {"ad5065", ID_AD5065}, 512*dbdc025bSLars-Peter Clausen {"ad5628-1", ID_AD5628_1}, 513*dbdc025bSLars-Peter Clausen {"ad5628-2", ID_AD5628_2}, 514*dbdc025bSLars-Peter Clausen {"ad5648-1", ID_AD5648_1}, 515*dbdc025bSLars-Peter Clausen {"ad5648-2", ID_AD5648_2}, 516*dbdc025bSLars-Peter Clausen {"ad5666-1", ID_AD5666_1}, 517*dbdc025bSLars-Peter Clausen {"ad5666-2", ID_AD5666_2}, 518*dbdc025bSLars-Peter Clausen {"ad5668-1", ID_AD5668_1}, 519*dbdc025bSLars-Peter Clausen {"ad5668-2", ID_AD5668_2}, 520*dbdc025bSLars-Peter Clausen {"ad5668-3", ID_AD5668_2}, /* similar enough to ad5668-2 */ 521*dbdc025bSLars-Peter Clausen {} 522*dbdc025bSLars-Peter Clausen }; 523*dbdc025bSLars-Peter Clausen MODULE_DEVICE_TABLE(spi, ad5064_id); 524*dbdc025bSLars-Peter Clausen 525*dbdc025bSLars-Peter Clausen static struct spi_driver ad5064_driver = { 526*dbdc025bSLars-Peter Clausen .driver = { 527*dbdc025bSLars-Peter Clausen .name = "ad5064", 528*dbdc025bSLars-Peter Clausen .owner = THIS_MODULE, 529*dbdc025bSLars-Peter Clausen }, 530*dbdc025bSLars-Peter Clausen .probe = ad5064_probe, 531*dbdc025bSLars-Peter Clausen .remove = __devexit_p(ad5064_remove), 532*dbdc025bSLars-Peter Clausen .id_table = ad5064_id, 533*dbdc025bSLars-Peter Clausen }; 534*dbdc025bSLars-Peter Clausen module_spi_driver(ad5064_driver); 535*dbdc025bSLars-Peter Clausen 536*dbdc025bSLars-Peter Clausen MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 537*dbdc025bSLars-Peter Clausen MODULE_DESCRIPTION("Analog Devices AD5024/25/44/45/64/64-1/65, AD5628/48/66/68 DAC"); 538*dbdc025bSLars-Peter Clausen MODULE_LICENSE("GPL v2"); 539