162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * AD5721, AD5721R, AD5761, AD5761R, Voltage Output Digital to Analog Converter 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2016 Qtechnology A/S 662306a36Sopenharmony_ci * 2016 Ricardo Ribalda <ribalda@kernel.org> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci#include <linux/kernel.h> 962306a36Sopenharmony_ci#include <linux/module.h> 1062306a36Sopenharmony_ci#include <linux/spi/spi.h> 1162306a36Sopenharmony_ci#include <linux/bitops.h> 1262306a36Sopenharmony_ci#include <linux/iio/iio.h> 1362306a36Sopenharmony_ci#include <linux/iio/sysfs.h> 1462306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 1562306a36Sopenharmony_ci#include <linux/platform_data/ad5761.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define AD5761_ADDR(addr) ((addr & 0xf) << 16) 1862306a36Sopenharmony_ci#define AD5761_ADDR_NOOP 0x0 1962306a36Sopenharmony_ci#define AD5761_ADDR_DAC_WRITE 0x3 2062306a36Sopenharmony_ci#define AD5761_ADDR_CTRL_WRITE_REG 0x4 2162306a36Sopenharmony_ci#define AD5761_ADDR_SW_DATA_RESET 0x7 2262306a36Sopenharmony_ci#define AD5761_ADDR_DAC_READ 0xb 2362306a36Sopenharmony_ci#define AD5761_ADDR_CTRL_READ_REG 0xc 2462306a36Sopenharmony_ci#define AD5761_ADDR_SW_FULL_RESET 0xf 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define AD5761_CTRL_USE_INTVREF BIT(5) 2762306a36Sopenharmony_ci#define AD5761_CTRL_ETS BIT(6) 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/** 3062306a36Sopenharmony_ci * struct ad5761_chip_info - chip specific information 3162306a36Sopenharmony_ci * @int_vref: Value of the internal reference voltage in mV - 0 if external 3262306a36Sopenharmony_ci * reference voltage is used 3362306a36Sopenharmony_ci * @channel: channel specification 3462306a36Sopenharmony_ci*/ 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistruct ad5761_chip_info { 3762306a36Sopenharmony_ci unsigned long int_vref; 3862306a36Sopenharmony_ci const struct iio_chan_spec channel; 3962306a36Sopenharmony_ci}; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistruct ad5761_range_params { 4262306a36Sopenharmony_ci int m; 4362306a36Sopenharmony_ci int c; 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cienum ad5761_supported_device_ids { 4762306a36Sopenharmony_ci ID_AD5721, 4862306a36Sopenharmony_ci ID_AD5721R, 4962306a36Sopenharmony_ci ID_AD5761, 5062306a36Sopenharmony_ci ID_AD5761R, 5162306a36Sopenharmony_ci}; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci/** 5462306a36Sopenharmony_ci * struct ad5761_state - driver instance specific data 5562306a36Sopenharmony_ci * @spi: spi_device 5662306a36Sopenharmony_ci * @vref_reg: reference voltage regulator 5762306a36Sopenharmony_ci * @use_intref: true when the internal voltage reference is used 5862306a36Sopenharmony_ci * @vref: actual voltage reference in mVolts 5962306a36Sopenharmony_ci * @range: output range mode used 6062306a36Sopenharmony_ci * @lock: lock to protect the data buffer during SPI ops 6162306a36Sopenharmony_ci * @data: cache aligned spi buffer 6262306a36Sopenharmony_ci */ 6362306a36Sopenharmony_cistruct ad5761_state { 6462306a36Sopenharmony_ci struct spi_device *spi; 6562306a36Sopenharmony_ci struct regulator *vref_reg; 6662306a36Sopenharmony_ci struct mutex lock; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci bool use_intref; 6962306a36Sopenharmony_ci int vref; 7062306a36Sopenharmony_ci enum ad5761_voltage_range range; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci /* 7362306a36Sopenharmony_ci * DMA (thus cache coherency maintenance) may require the 7462306a36Sopenharmony_ci * transfer buffers to live in their own cache lines. 7562306a36Sopenharmony_ci */ 7662306a36Sopenharmony_ci union { 7762306a36Sopenharmony_ci __be32 d32; 7862306a36Sopenharmony_ci u8 d8[4]; 7962306a36Sopenharmony_ci } data[3] __aligned(IIO_DMA_MINALIGN); 8062306a36Sopenharmony_ci}; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic const struct ad5761_range_params ad5761_range_params[] = { 8362306a36Sopenharmony_ci [AD5761_VOLTAGE_RANGE_M10V_10V] = { 8462306a36Sopenharmony_ci .m = 80, 8562306a36Sopenharmony_ci .c = 40, 8662306a36Sopenharmony_ci }, 8762306a36Sopenharmony_ci [AD5761_VOLTAGE_RANGE_0V_10V] = { 8862306a36Sopenharmony_ci .m = 40, 8962306a36Sopenharmony_ci .c = 0, 9062306a36Sopenharmony_ci }, 9162306a36Sopenharmony_ci [AD5761_VOLTAGE_RANGE_M5V_5V] = { 9262306a36Sopenharmony_ci .m = 40, 9362306a36Sopenharmony_ci .c = 20, 9462306a36Sopenharmony_ci }, 9562306a36Sopenharmony_ci [AD5761_VOLTAGE_RANGE_0V_5V] = { 9662306a36Sopenharmony_ci .m = 20, 9762306a36Sopenharmony_ci .c = 0, 9862306a36Sopenharmony_ci }, 9962306a36Sopenharmony_ci [AD5761_VOLTAGE_RANGE_M2V5_7V5] = { 10062306a36Sopenharmony_ci .m = 40, 10162306a36Sopenharmony_ci .c = 10, 10262306a36Sopenharmony_ci }, 10362306a36Sopenharmony_ci [AD5761_VOLTAGE_RANGE_M3V_3V] = { 10462306a36Sopenharmony_ci .m = 24, 10562306a36Sopenharmony_ci .c = 12, 10662306a36Sopenharmony_ci }, 10762306a36Sopenharmony_ci [AD5761_VOLTAGE_RANGE_0V_16V] = { 10862306a36Sopenharmony_ci .m = 64, 10962306a36Sopenharmony_ci .c = 0, 11062306a36Sopenharmony_ci }, 11162306a36Sopenharmony_ci [AD5761_VOLTAGE_RANGE_0V_20V] = { 11262306a36Sopenharmony_ci .m = 80, 11362306a36Sopenharmony_ci .c = 0, 11462306a36Sopenharmony_ci }, 11562306a36Sopenharmony_ci}; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_cistatic int _ad5761_spi_write(struct ad5761_state *st, u8 addr, u16 val) 11862306a36Sopenharmony_ci{ 11962306a36Sopenharmony_ci st->data[0].d32 = cpu_to_be32(AD5761_ADDR(addr) | val); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci return spi_write(st->spi, &st->data[0].d8[1], 3); 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic int ad5761_spi_write(struct iio_dev *indio_dev, u8 addr, u16 val) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci struct ad5761_state *st = iio_priv(indio_dev); 12762306a36Sopenharmony_ci int ret; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci mutex_lock(&st->lock); 13062306a36Sopenharmony_ci ret = _ad5761_spi_write(st, addr, val); 13162306a36Sopenharmony_ci mutex_unlock(&st->lock); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci return ret; 13462306a36Sopenharmony_ci} 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic int _ad5761_spi_read(struct ad5761_state *st, u8 addr, u16 *val) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci int ret; 13962306a36Sopenharmony_ci struct spi_transfer xfers[] = { 14062306a36Sopenharmony_ci { 14162306a36Sopenharmony_ci .tx_buf = &st->data[0].d8[1], 14262306a36Sopenharmony_ci .bits_per_word = 8, 14362306a36Sopenharmony_ci .len = 3, 14462306a36Sopenharmony_ci .cs_change = true, 14562306a36Sopenharmony_ci }, { 14662306a36Sopenharmony_ci .tx_buf = &st->data[1].d8[1], 14762306a36Sopenharmony_ci .rx_buf = &st->data[2].d8[1], 14862306a36Sopenharmony_ci .bits_per_word = 8, 14962306a36Sopenharmony_ci .len = 3, 15062306a36Sopenharmony_ci }, 15162306a36Sopenharmony_ci }; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci st->data[0].d32 = cpu_to_be32(AD5761_ADDR(addr)); 15462306a36Sopenharmony_ci st->data[1].d32 = cpu_to_be32(AD5761_ADDR(AD5761_ADDR_NOOP)); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci *val = be32_to_cpu(st->data[2].d32); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci return ret; 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic int ad5761_spi_read(struct iio_dev *indio_dev, u8 addr, u16 *val) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci struct ad5761_state *st = iio_priv(indio_dev); 16662306a36Sopenharmony_ci int ret; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci mutex_lock(&st->lock); 16962306a36Sopenharmony_ci ret = _ad5761_spi_read(st, addr, val); 17062306a36Sopenharmony_ci mutex_unlock(&st->lock); 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci return ret; 17362306a36Sopenharmony_ci} 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_cistatic int ad5761_spi_set_range(struct ad5761_state *st, 17662306a36Sopenharmony_ci enum ad5761_voltage_range range) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci u16 aux; 17962306a36Sopenharmony_ci int ret; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci aux = (range & 0x7) | AD5761_CTRL_ETS; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci if (st->use_intref) 18462306a36Sopenharmony_ci aux |= AD5761_CTRL_USE_INTVREF; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci ret = _ad5761_spi_write(st, AD5761_ADDR_SW_FULL_RESET, 0); 18762306a36Sopenharmony_ci if (ret) 18862306a36Sopenharmony_ci return ret; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci ret = _ad5761_spi_write(st, AD5761_ADDR_CTRL_WRITE_REG, aux); 19162306a36Sopenharmony_ci if (ret) 19262306a36Sopenharmony_ci return ret; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci st->range = range; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci return 0; 19762306a36Sopenharmony_ci} 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_cistatic int ad5761_read_raw(struct iio_dev *indio_dev, 20062306a36Sopenharmony_ci struct iio_chan_spec const *chan, 20162306a36Sopenharmony_ci int *val, 20262306a36Sopenharmony_ci int *val2, 20362306a36Sopenharmony_ci long mask) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci struct ad5761_state *st; 20662306a36Sopenharmony_ci int ret; 20762306a36Sopenharmony_ci u16 aux; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci switch (mask) { 21062306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 21162306a36Sopenharmony_ci ret = ad5761_spi_read(indio_dev, AD5761_ADDR_DAC_READ, &aux); 21262306a36Sopenharmony_ci if (ret) 21362306a36Sopenharmony_ci return ret; 21462306a36Sopenharmony_ci *val = aux >> chan->scan_type.shift; 21562306a36Sopenharmony_ci return IIO_VAL_INT; 21662306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 21762306a36Sopenharmony_ci st = iio_priv(indio_dev); 21862306a36Sopenharmony_ci *val = st->vref * ad5761_range_params[st->range].m; 21962306a36Sopenharmony_ci *val /= 10; 22062306a36Sopenharmony_ci *val2 = chan->scan_type.realbits; 22162306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL_LOG2; 22262306a36Sopenharmony_ci case IIO_CHAN_INFO_OFFSET: 22362306a36Sopenharmony_ci st = iio_priv(indio_dev); 22462306a36Sopenharmony_ci *val = -(1 << chan->scan_type.realbits); 22562306a36Sopenharmony_ci *val *= ad5761_range_params[st->range].c; 22662306a36Sopenharmony_ci *val /= ad5761_range_params[st->range].m; 22762306a36Sopenharmony_ci return IIO_VAL_INT; 22862306a36Sopenharmony_ci default: 22962306a36Sopenharmony_ci return -EINVAL; 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci} 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_cistatic int ad5761_write_raw(struct iio_dev *indio_dev, 23462306a36Sopenharmony_ci struct iio_chan_spec const *chan, 23562306a36Sopenharmony_ci int val, 23662306a36Sopenharmony_ci int val2, 23762306a36Sopenharmony_ci long mask) 23862306a36Sopenharmony_ci{ 23962306a36Sopenharmony_ci u16 aux; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci if (mask != IIO_CHAN_INFO_RAW) 24262306a36Sopenharmony_ci return -EINVAL; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci if (val2 || (val << chan->scan_type.shift) > 0xffff || val < 0) 24562306a36Sopenharmony_ci return -EINVAL; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci aux = val << chan->scan_type.shift; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci return ad5761_spi_write(indio_dev, AD5761_ADDR_DAC_WRITE, aux); 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_cistatic const struct iio_info ad5761_info = { 25362306a36Sopenharmony_ci .read_raw = &ad5761_read_raw, 25462306a36Sopenharmony_ci .write_raw = &ad5761_write_raw, 25562306a36Sopenharmony_ci}; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci#define AD5761_CHAN(_bits) { \ 25862306a36Sopenharmony_ci .type = IIO_VOLTAGE, \ 25962306a36Sopenharmony_ci .output = 1, \ 26062306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 26162306a36Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 26262306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_OFFSET), \ 26362306a36Sopenharmony_ci .scan_type = { \ 26462306a36Sopenharmony_ci .sign = 'u', \ 26562306a36Sopenharmony_ci .realbits = (_bits), \ 26662306a36Sopenharmony_ci .storagebits = 16, \ 26762306a36Sopenharmony_ci .shift = 16 - (_bits), \ 26862306a36Sopenharmony_ci }, \ 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_cistatic const struct ad5761_chip_info ad5761_chip_infos[] = { 27262306a36Sopenharmony_ci [ID_AD5721] = { 27362306a36Sopenharmony_ci .int_vref = 0, 27462306a36Sopenharmony_ci .channel = AD5761_CHAN(12), 27562306a36Sopenharmony_ci }, 27662306a36Sopenharmony_ci [ID_AD5721R] = { 27762306a36Sopenharmony_ci .int_vref = 2500, 27862306a36Sopenharmony_ci .channel = AD5761_CHAN(12), 27962306a36Sopenharmony_ci }, 28062306a36Sopenharmony_ci [ID_AD5761] = { 28162306a36Sopenharmony_ci .int_vref = 0, 28262306a36Sopenharmony_ci .channel = AD5761_CHAN(16), 28362306a36Sopenharmony_ci }, 28462306a36Sopenharmony_ci [ID_AD5761R] = { 28562306a36Sopenharmony_ci .int_vref = 2500, 28662306a36Sopenharmony_ci .channel = AD5761_CHAN(16), 28762306a36Sopenharmony_ci }, 28862306a36Sopenharmony_ci}; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cistatic int ad5761_get_vref(struct ad5761_state *st, 29162306a36Sopenharmony_ci const struct ad5761_chip_info *chip_info) 29262306a36Sopenharmony_ci{ 29362306a36Sopenharmony_ci int ret; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci st->vref_reg = devm_regulator_get_optional(&st->spi->dev, "vref"); 29662306a36Sopenharmony_ci if (PTR_ERR(st->vref_reg) == -ENODEV) { 29762306a36Sopenharmony_ci /* Use Internal regulator */ 29862306a36Sopenharmony_ci if (!chip_info->int_vref) { 29962306a36Sopenharmony_ci dev_err(&st->spi->dev, 30062306a36Sopenharmony_ci "Voltage reference not found\n"); 30162306a36Sopenharmony_ci return -EIO; 30262306a36Sopenharmony_ci } 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci st->use_intref = true; 30562306a36Sopenharmony_ci st->vref = chip_info->int_vref; 30662306a36Sopenharmony_ci return 0; 30762306a36Sopenharmony_ci } 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci if (IS_ERR(st->vref_reg)) { 31062306a36Sopenharmony_ci dev_err(&st->spi->dev, 31162306a36Sopenharmony_ci "Error getting voltage reference regulator\n"); 31262306a36Sopenharmony_ci return PTR_ERR(st->vref_reg); 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci ret = regulator_enable(st->vref_reg); 31662306a36Sopenharmony_ci if (ret) { 31762306a36Sopenharmony_ci dev_err(&st->spi->dev, 31862306a36Sopenharmony_ci "Failed to enable voltage reference\n"); 31962306a36Sopenharmony_ci return ret; 32062306a36Sopenharmony_ci } 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci ret = regulator_get_voltage(st->vref_reg); 32362306a36Sopenharmony_ci if (ret < 0) { 32462306a36Sopenharmony_ci dev_err(&st->spi->dev, 32562306a36Sopenharmony_ci "Failed to get voltage reference value\n"); 32662306a36Sopenharmony_ci goto disable_regulator_vref; 32762306a36Sopenharmony_ci } 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci if (ret < 2000000 || ret > 3000000) { 33062306a36Sopenharmony_ci dev_warn(&st->spi->dev, 33162306a36Sopenharmony_ci "Invalid external voltage ref. value %d uV\n", ret); 33262306a36Sopenharmony_ci ret = -EIO; 33362306a36Sopenharmony_ci goto disable_regulator_vref; 33462306a36Sopenharmony_ci } 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci st->vref = ret / 1000; 33762306a36Sopenharmony_ci st->use_intref = false; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci return 0; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_cidisable_regulator_vref: 34262306a36Sopenharmony_ci regulator_disable(st->vref_reg); 34362306a36Sopenharmony_ci st->vref_reg = NULL; 34462306a36Sopenharmony_ci return ret; 34562306a36Sopenharmony_ci} 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_cistatic int ad5761_probe(struct spi_device *spi) 34862306a36Sopenharmony_ci{ 34962306a36Sopenharmony_ci struct iio_dev *iio_dev; 35062306a36Sopenharmony_ci struct ad5761_state *st; 35162306a36Sopenharmony_ci int ret; 35262306a36Sopenharmony_ci const struct ad5761_chip_info *chip_info = 35362306a36Sopenharmony_ci &ad5761_chip_infos[spi_get_device_id(spi)->driver_data]; 35462306a36Sopenharmony_ci enum ad5761_voltage_range voltage_range = AD5761_VOLTAGE_RANGE_0V_5V; 35562306a36Sopenharmony_ci struct ad5761_platform_data *pdata = dev_get_platdata(&spi->dev); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci iio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 35862306a36Sopenharmony_ci if (!iio_dev) 35962306a36Sopenharmony_ci return -ENOMEM; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci st = iio_priv(iio_dev); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci st->spi = spi; 36462306a36Sopenharmony_ci spi_set_drvdata(spi, iio_dev); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci ret = ad5761_get_vref(st, chip_info); 36762306a36Sopenharmony_ci if (ret) 36862306a36Sopenharmony_ci return ret; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci if (pdata) 37162306a36Sopenharmony_ci voltage_range = pdata->voltage_range; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci mutex_init(&st->lock); 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci ret = ad5761_spi_set_range(st, voltage_range); 37662306a36Sopenharmony_ci if (ret) 37762306a36Sopenharmony_ci goto disable_regulator_err; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci iio_dev->info = &ad5761_info; 38062306a36Sopenharmony_ci iio_dev->modes = INDIO_DIRECT_MODE; 38162306a36Sopenharmony_ci iio_dev->channels = &chip_info->channel; 38262306a36Sopenharmony_ci iio_dev->num_channels = 1; 38362306a36Sopenharmony_ci iio_dev->name = spi_get_device_id(st->spi)->name; 38462306a36Sopenharmony_ci ret = iio_device_register(iio_dev); 38562306a36Sopenharmony_ci if (ret) 38662306a36Sopenharmony_ci goto disable_regulator_err; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci return 0; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_cidisable_regulator_err: 39162306a36Sopenharmony_ci if (!IS_ERR_OR_NULL(st->vref_reg)) 39262306a36Sopenharmony_ci regulator_disable(st->vref_reg); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci return ret; 39562306a36Sopenharmony_ci} 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_cistatic void ad5761_remove(struct spi_device *spi) 39862306a36Sopenharmony_ci{ 39962306a36Sopenharmony_ci struct iio_dev *iio_dev = spi_get_drvdata(spi); 40062306a36Sopenharmony_ci struct ad5761_state *st = iio_priv(iio_dev); 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci iio_device_unregister(iio_dev); 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci if (!IS_ERR_OR_NULL(st->vref_reg)) 40562306a36Sopenharmony_ci regulator_disable(st->vref_reg); 40662306a36Sopenharmony_ci} 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_cistatic const struct spi_device_id ad5761_id[] = { 40962306a36Sopenharmony_ci {"ad5721", ID_AD5721}, 41062306a36Sopenharmony_ci {"ad5721r", ID_AD5721R}, 41162306a36Sopenharmony_ci {"ad5761", ID_AD5761}, 41262306a36Sopenharmony_ci {"ad5761r", ID_AD5761R}, 41362306a36Sopenharmony_ci {} 41462306a36Sopenharmony_ci}; 41562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, ad5761_id); 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_cistatic struct spi_driver ad5761_driver = { 41862306a36Sopenharmony_ci .driver = { 41962306a36Sopenharmony_ci .name = "ad5761", 42062306a36Sopenharmony_ci }, 42162306a36Sopenharmony_ci .probe = ad5761_probe, 42262306a36Sopenharmony_ci .remove = ad5761_remove, 42362306a36Sopenharmony_ci .id_table = ad5761_id, 42462306a36Sopenharmony_ci}; 42562306a36Sopenharmony_cimodule_spi_driver(ad5761_driver); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ciMODULE_AUTHOR("Ricardo Ribalda <ribalda@kernel.org>"); 42862306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices AD5721, AD5721R, AD5761, AD5761R driver"); 42962306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 430