162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5625, AD5625R, 462306a36Sopenharmony_ci * AD5627, AD5627R, AD5628, AD5629R, AD5645R, AD5647R, AD5648, AD5665, AD5665R, 562306a36Sopenharmony_ci * AD5666, AD5667, AD5667R, AD5668, AD5669R, LTC2606, LTC2607, LTC2609, LTC2616, 662306a36Sopenharmony_ci * LTC2617, LTC2619, LTC2626, LTC2627, LTC2629, LTC2631, LTC2633, LTC2635 762306a36Sopenharmony_ci * Digital to analog converters driver 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Copyright 2011 Analog Devices Inc. 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/device.h> 1362306a36Sopenharmony_ci#include <linux/err.h> 1462306a36Sopenharmony_ci#include <linux/module.h> 1562306a36Sopenharmony_ci#include <linux/kernel.h> 1662306a36Sopenharmony_ci#include <linux/spi/spi.h> 1762306a36Sopenharmony_ci#include <linux/i2c.h> 1862306a36Sopenharmony_ci#include <linux/slab.h> 1962306a36Sopenharmony_ci#include <linux/sysfs.h> 2062306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 2162306a36Sopenharmony_ci#include <asm/unaligned.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include <linux/iio/iio.h> 2462306a36Sopenharmony_ci#include <linux/iio/sysfs.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define AD5064_MAX_DAC_CHANNELS 8 2762306a36Sopenharmony_ci#define AD5064_MAX_VREFS 4 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#define AD5064_ADDR(x) ((x) << 20) 3062306a36Sopenharmony_ci#define AD5064_CMD(x) ((x) << 24) 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#define AD5064_ADDR_ALL_DAC 0xF 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define AD5064_CMD_WRITE_INPUT_N 0x0 3562306a36Sopenharmony_ci#define AD5064_CMD_UPDATE_DAC_N 0x1 3662306a36Sopenharmony_ci#define AD5064_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2 3762306a36Sopenharmony_ci#define AD5064_CMD_WRITE_INPUT_N_UPDATE_N 0x3 3862306a36Sopenharmony_ci#define AD5064_CMD_POWERDOWN_DAC 0x4 3962306a36Sopenharmony_ci#define AD5064_CMD_CLEAR 0x5 4062306a36Sopenharmony_ci#define AD5064_CMD_LDAC_MASK 0x6 4162306a36Sopenharmony_ci#define AD5064_CMD_RESET 0x7 4262306a36Sopenharmony_ci#define AD5064_CMD_CONFIG 0x8 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define AD5064_CMD_RESET_V2 0x5 4562306a36Sopenharmony_ci#define AD5064_CMD_CONFIG_V2 0x7 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#define AD5064_CONFIG_DAISY_CHAIN_ENABLE BIT(1) 4862306a36Sopenharmony_ci#define AD5064_CONFIG_INT_VREF_ENABLE BIT(0) 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#define AD5064_LDAC_PWRDN_NONE 0x0 5162306a36Sopenharmony_ci#define AD5064_LDAC_PWRDN_1K 0x1 5262306a36Sopenharmony_ci#define AD5064_LDAC_PWRDN_100K 0x2 5362306a36Sopenharmony_ci#define AD5064_LDAC_PWRDN_3STATE 0x3 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci/** 5662306a36Sopenharmony_ci * enum ad5064_regmap_type - Register layout variant 5762306a36Sopenharmony_ci * @AD5064_REGMAP_ADI: Old Analog Devices register map layout 5862306a36Sopenharmony_ci * @AD5064_REGMAP_ADI2: New Analog Devices register map layout 5962306a36Sopenharmony_ci * @AD5064_REGMAP_LTC: LTC register map layout 6062306a36Sopenharmony_ci */ 6162306a36Sopenharmony_cienum ad5064_regmap_type { 6262306a36Sopenharmony_ci AD5064_REGMAP_ADI, 6362306a36Sopenharmony_ci AD5064_REGMAP_ADI2, 6462306a36Sopenharmony_ci AD5064_REGMAP_LTC, 6562306a36Sopenharmony_ci}; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci/** 6862306a36Sopenharmony_ci * struct ad5064_chip_info - chip specific information 6962306a36Sopenharmony_ci * @shared_vref: whether the vref supply is shared between channels 7062306a36Sopenharmony_ci * @internal_vref: internal reference voltage. 0 if the chip has no 7162306a36Sopenharmony_ci * internal vref. 7262306a36Sopenharmony_ci * @channels: channel specification 7362306a36Sopenharmony_ci * @num_channels: number of channels 7462306a36Sopenharmony_ci * @regmap_type: register map layout variant 7562306a36Sopenharmony_ci */ 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistruct ad5064_chip_info { 7862306a36Sopenharmony_ci bool shared_vref; 7962306a36Sopenharmony_ci unsigned long internal_vref; 8062306a36Sopenharmony_ci const struct iio_chan_spec *channels; 8162306a36Sopenharmony_ci unsigned int num_channels; 8262306a36Sopenharmony_ci enum ad5064_regmap_type regmap_type; 8362306a36Sopenharmony_ci}; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistruct ad5064_state; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_citypedef int (*ad5064_write_func)(struct ad5064_state *st, unsigned int cmd, 8862306a36Sopenharmony_ci unsigned int addr, unsigned int val); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci/** 9162306a36Sopenharmony_ci * struct ad5064_state - driver instance specific data 9262306a36Sopenharmony_ci * @dev: the device for this driver instance 9362306a36Sopenharmony_ci * @chip_info: chip model specific constants, available modes etc 9462306a36Sopenharmony_ci * @vref_reg: vref supply regulators 9562306a36Sopenharmony_ci * @pwr_down: whether channel is powered down 9662306a36Sopenharmony_ci * @pwr_down_mode: channel's current power down mode 9762306a36Sopenharmony_ci * @dac_cache: current DAC raw value (chip does not support readback) 9862306a36Sopenharmony_ci * @use_internal_vref: set to true if the internal reference voltage should be 9962306a36Sopenharmony_ci * used. 10062306a36Sopenharmony_ci * @write: register write callback 10162306a36Sopenharmony_ci * @lock: maintain consistency between cached and dev state 10262306a36Sopenharmony_ci * @data: i2c/spi transfer buffers 10362306a36Sopenharmony_ci */ 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistruct ad5064_state { 10662306a36Sopenharmony_ci struct device *dev; 10762306a36Sopenharmony_ci const struct ad5064_chip_info *chip_info; 10862306a36Sopenharmony_ci struct regulator_bulk_data vref_reg[AD5064_MAX_VREFS]; 10962306a36Sopenharmony_ci bool pwr_down[AD5064_MAX_DAC_CHANNELS]; 11062306a36Sopenharmony_ci u8 pwr_down_mode[AD5064_MAX_DAC_CHANNELS]; 11162306a36Sopenharmony_ci unsigned int dac_cache[AD5064_MAX_DAC_CHANNELS]; 11262306a36Sopenharmony_ci bool use_internal_vref; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci ad5064_write_func write; 11562306a36Sopenharmony_ci struct mutex lock; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* 11862306a36Sopenharmony_ci * DMA (thus cache coherency maintenance) may require the 11962306a36Sopenharmony_ci * transfer buffers to live in their own cache lines. 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_ci union { 12262306a36Sopenharmony_ci u8 i2c[3]; 12362306a36Sopenharmony_ci __be32 spi; 12462306a36Sopenharmony_ci } data __aligned(IIO_DMA_MINALIGN); 12562306a36Sopenharmony_ci}; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cienum ad5064_type { 12862306a36Sopenharmony_ci ID_AD5024, 12962306a36Sopenharmony_ci ID_AD5025, 13062306a36Sopenharmony_ci ID_AD5044, 13162306a36Sopenharmony_ci ID_AD5045, 13262306a36Sopenharmony_ci ID_AD5064, 13362306a36Sopenharmony_ci ID_AD5064_1, 13462306a36Sopenharmony_ci ID_AD5065, 13562306a36Sopenharmony_ci ID_AD5625, 13662306a36Sopenharmony_ci ID_AD5625R_1V25, 13762306a36Sopenharmony_ci ID_AD5625R_2V5, 13862306a36Sopenharmony_ci ID_AD5627, 13962306a36Sopenharmony_ci ID_AD5627R_1V25, 14062306a36Sopenharmony_ci ID_AD5627R_2V5, 14162306a36Sopenharmony_ci ID_AD5628_1, 14262306a36Sopenharmony_ci ID_AD5628_2, 14362306a36Sopenharmony_ci ID_AD5629_1, 14462306a36Sopenharmony_ci ID_AD5629_2, 14562306a36Sopenharmony_ci ID_AD5645R_1V25, 14662306a36Sopenharmony_ci ID_AD5645R_2V5, 14762306a36Sopenharmony_ci ID_AD5647R_1V25, 14862306a36Sopenharmony_ci ID_AD5647R_2V5, 14962306a36Sopenharmony_ci ID_AD5648_1, 15062306a36Sopenharmony_ci ID_AD5648_2, 15162306a36Sopenharmony_ci ID_AD5665, 15262306a36Sopenharmony_ci ID_AD5665R_1V25, 15362306a36Sopenharmony_ci ID_AD5665R_2V5, 15462306a36Sopenharmony_ci ID_AD5666_1, 15562306a36Sopenharmony_ci ID_AD5666_2, 15662306a36Sopenharmony_ci ID_AD5667, 15762306a36Sopenharmony_ci ID_AD5667R_1V25, 15862306a36Sopenharmony_ci ID_AD5667R_2V5, 15962306a36Sopenharmony_ci ID_AD5668_1, 16062306a36Sopenharmony_ci ID_AD5668_2, 16162306a36Sopenharmony_ci ID_AD5669_1, 16262306a36Sopenharmony_ci ID_AD5669_2, 16362306a36Sopenharmony_ci ID_LTC2606, 16462306a36Sopenharmony_ci ID_LTC2607, 16562306a36Sopenharmony_ci ID_LTC2609, 16662306a36Sopenharmony_ci ID_LTC2616, 16762306a36Sopenharmony_ci ID_LTC2617, 16862306a36Sopenharmony_ci ID_LTC2619, 16962306a36Sopenharmony_ci ID_LTC2626, 17062306a36Sopenharmony_ci ID_LTC2627, 17162306a36Sopenharmony_ci ID_LTC2629, 17262306a36Sopenharmony_ci ID_LTC2631_L12, 17362306a36Sopenharmony_ci ID_LTC2631_H12, 17462306a36Sopenharmony_ci ID_LTC2631_L10, 17562306a36Sopenharmony_ci ID_LTC2631_H10, 17662306a36Sopenharmony_ci ID_LTC2631_L8, 17762306a36Sopenharmony_ci ID_LTC2631_H8, 17862306a36Sopenharmony_ci ID_LTC2633_L12, 17962306a36Sopenharmony_ci ID_LTC2633_H12, 18062306a36Sopenharmony_ci ID_LTC2633_L10, 18162306a36Sopenharmony_ci ID_LTC2633_H10, 18262306a36Sopenharmony_ci ID_LTC2633_L8, 18362306a36Sopenharmony_ci ID_LTC2633_H8, 18462306a36Sopenharmony_ci ID_LTC2635_L12, 18562306a36Sopenharmony_ci ID_LTC2635_H12, 18662306a36Sopenharmony_ci ID_LTC2635_L10, 18762306a36Sopenharmony_ci ID_LTC2635_H10, 18862306a36Sopenharmony_ci ID_LTC2635_L8, 18962306a36Sopenharmony_ci ID_LTC2635_H8, 19062306a36Sopenharmony_ci}; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic int ad5064_write(struct ad5064_state *st, unsigned int cmd, 19362306a36Sopenharmony_ci unsigned int addr, unsigned int val, unsigned int shift) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci val <<= shift; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci return st->write(st, cmd, addr, val); 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic int ad5064_sync_powerdown_mode(struct ad5064_state *st, 20162306a36Sopenharmony_ci const struct iio_chan_spec *chan) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci unsigned int val, address; 20462306a36Sopenharmony_ci unsigned int shift; 20562306a36Sopenharmony_ci int ret; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci if (st->chip_info->regmap_type == AD5064_REGMAP_LTC) { 20862306a36Sopenharmony_ci val = 0; 20962306a36Sopenharmony_ci address = chan->address; 21062306a36Sopenharmony_ci } else { 21162306a36Sopenharmony_ci if (st->chip_info->regmap_type == AD5064_REGMAP_ADI2) 21262306a36Sopenharmony_ci shift = 4; 21362306a36Sopenharmony_ci else 21462306a36Sopenharmony_ci shift = 8; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci val = (0x1 << chan->address); 21762306a36Sopenharmony_ci address = 0; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci if (st->pwr_down[chan->channel]) 22062306a36Sopenharmony_ci val |= st->pwr_down_mode[chan->channel] << shift; 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci ret = ad5064_write(st, AD5064_CMD_POWERDOWN_DAC, address, val, 0); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci return ret; 22662306a36Sopenharmony_ci} 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_cistatic const char * const ad5064_powerdown_modes[] = { 22962306a36Sopenharmony_ci "1kohm_to_gnd", 23062306a36Sopenharmony_ci "100kohm_to_gnd", 23162306a36Sopenharmony_ci "three_state", 23262306a36Sopenharmony_ci}; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cistatic const char * const ltc2617_powerdown_modes[] = { 23562306a36Sopenharmony_ci "90kohm_to_gnd", 23662306a36Sopenharmony_ci}; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cistatic int ad5064_get_powerdown_mode(struct iio_dev *indio_dev, 23962306a36Sopenharmony_ci const struct iio_chan_spec *chan) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci struct ad5064_state *st = iio_priv(indio_dev); 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci return st->pwr_down_mode[chan->channel] - 1; 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_cistatic int ad5064_set_powerdown_mode(struct iio_dev *indio_dev, 24762306a36Sopenharmony_ci const struct iio_chan_spec *chan, unsigned int mode) 24862306a36Sopenharmony_ci{ 24962306a36Sopenharmony_ci struct ad5064_state *st = iio_priv(indio_dev); 25062306a36Sopenharmony_ci int ret; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci mutex_lock(&st->lock); 25362306a36Sopenharmony_ci st->pwr_down_mode[chan->channel] = mode + 1; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci ret = ad5064_sync_powerdown_mode(st, chan); 25662306a36Sopenharmony_ci mutex_unlock(&st->lock); 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci return ret; 25962306a36Sopenharmony_ci} 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistatic const struct iio_enum ad5064_powerdown_mode_enum = { 26262306a36Sopenharmony_ci .items = ad5064_powerdown_modes, 26362306a36Sopenharmony_ci .num_items = ARRAY_SIZE(ad5064_powerdown_modes), 26462306a36Sopenharmony_ci .get = ad5064_get_powerdown_mode, 26562306a36Sopenharmony_ci .set = ad5064_set_powerdown_mode, 26662306a36Sopenharmony_ci}; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_cistatic const struct iio_enum ltc2617_powerdown_mode_enum = { 26962306a36Sopenharmony_ci .items = ltc2617_powerdown_modes, 27062306a36Sopenharmony_ci .num_items = ARRAY_SIZE(ltc2617_powerdown_modes), 27162306a36Sopenharmony_ci .get = ad5064_get_powerdown_mode, 27262306a36Sopenharmony_ci .set = ad5064_set_powerdown_mode, 27362306a36Sopenharmony_ci}; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_cistatic ssize_t ad5064_read_dac_powerdown(struct iio_dev *indio_dev, 27662306a36Sopenharmony_ci uintptr_t private, const struct iio_chan_spec *chan, char *buf) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci struct ad5064_state *st = iio_priv(indio_dev); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci return sysfs_emit(buf, "%d\n", st->pwr_down[chan->channel]); 28162306a36Sopenharmony_ci} 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic ssize_t ad5064_write_dac_powerdown(struct iio_dev *indio_dev, 28462306a36Sopenharmony_ci uintptr_t private, const struct iio_chan_spec *chan, const char *buf, 28562306a36Sopenharmony_ci size_t len) 28662306a36Sopenharmony_ci{ 28762306a36Sopenharmony_ci struct ad5064_state *st = iio_priv(indio_dev); 28862306a36Sopenharmony_ci bool pwr_down; 28962306a36Sopenharmony_ci int ret; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci ret = kstrtobool(buf, &pwr_down); 29262306a36Sopenharmony_ci if (ret) 29362306a36Sopenharmony_ci return ret; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci mutex_lock(&st->lock); 29662306a36Sopenharmony_ci st->pwr_down[chan->channel] = pwr_down; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci ret = ad5064_sync_powerdown_mode(st, chan); 29962306a36Sopenharmony_ci mutex_unlock(&st->lock); 30062306a36Sopenharmony_ci return ret ? ret : len; 30162306a36Sopenharmony_ci} 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_cistatic int ad5064_get_vref(struct ad5064_state *st, 30462306a36Sopenharmony_ci struct iio_chan_spec const *chan) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci unsigned int i; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci if (st->use_internal_vref) 30962306a36Sopenharmony_ci return st->chip_info->internal_vref; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci i = st->chip_info->shared_vref ? 0 : chan->channel; 31262306a36Sopenharmony_ci return regulator_get_voltage(st->vref_reg[i].consumer); 31362306a36Sopenharmony_ci} 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_cistatic int ad5064_read_raw(struct iio_dev *indio_dev, 31662306a36Sopenharmony_ci struct iio_chan_spec const *chan, 31762306a36Sopenharmony_ci int *val, 31862306a36Sopenharmony_ci int *val2, 31962306a36Sopenharmony_ci long m) 32062306a36Sopenharmony_ci{ 32162306a36Sopenharmony_ci struct ad5064_state *st = iio_priv(indio_dev); 32262306a36Sopenharmony_ci int scale_uv; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci switch (m) { 32562306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 32662306a36Sopenharmony_ci *val = st->dac_cache[chan->channel]; 32762306a36Sopenharmony_ci return IIO_VAL_INT; 32862306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 32962306a36Sopenharmony_ci scale_uv = ad5064_get_vref(st, chan); 33062306a36Sopenharmony_ci if (scale_uv < 0) 33162306a36Sopenharmony_ci return scale_uv; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci *val = scale_uv / 1000; 33462306a36Sopenharmony_ci *val2 = chan->scan_type.realbits; 33562306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL_LOG2; 33662306a36Sopenharmony_ci default: 33762306a36Sopenharmony_ci break; 33862306a36Sopenharmony_ci } 33962306a36Sopenharmony_ci return -EINVAL; 34062306a36Sopenharmony_ci} 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_cistatic int ad5064_write_raw(struct iio_dev *indio_dev, 34362306a36Sopenharmony_ci struct iio_chan_spec const *chan, int val, int val2, long mask) 34462306a36Sopenharmony_ci{ 34562306a36Sopenharmony_ci struct ad5064_state *st = iio_priv(indio_dev); 34662306a36Sopenharmony_ci int ret; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci switch (mask) { 34962306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 35062306a36Sopenharmony_ci if (val >= (1 << chan->scan_type.realbits) || val < 0) 35162306a36Sopenharmony_ci return -EINVAL; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci mutex_lock(&st->lock); 35462306a36Sopenharmony_ci ret = ad5064_write(st, AD5064_CMD_WRITE_INPUT_N_UPDATE_N, 35562306a36Sopenharmony_ci chan->address, val, chan->scan_type.shift); 35662306a36Sopenharmony_ci if (ret == 0) 35762306a36Sopenharmony_ci st->dac_cache[chan->channel] = val; 35862306a36Sopenharmony_ci mutex_unlock(&st->lock); 35962306a36Sopenharmony_ci break; 36062306a36Sopenharmony_ci default: 36162306a36Sopenharmony_ci ret = -EINVAL; 36262306a36Sopenharmony_ci } 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci return ret; 36562306a36Sopenharmony_ci} 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cistatic const struct iio_info ad5064_info = { 36862306a36Sopenharmony_ci .read_raw = ad5064_read_raw, 36962306a36Sopenharmony_ci .write_raw = ad5064_write_raw, 37062306a36Sopenharmony_ci}; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_cistatic const struct iio_chan_spec_ext_info ad5064_ext_info[] = { 37362306a36Sopenharmony_ci { 37462306a36Sopenharmony_ci .name = "powerdown", 37562306a36Sopenharmony_ci .read = ad5064_read_dac_powerdown, 37662306a36Sopenharmony_ci .write = ad5064_write_dac_powerdown, 37762306a36Sopenharmony_ci .shared = IIO_SEPARATE, 37862306a36Sopenharmony_ci }, 37962306a36Sopenharmony_ci IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5064_powerdown_mode_enum), 38062306a36Sopenharmony_ci IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5064_powerdown_mode_enum), 38162306a36Sopenharmony_ci { }, 38262306a36Sopenharmony_ci}; 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_cistatic const struct iio_chan_spec_ext_info ltc2617_ext_info[] = { 38562306a36Sopenharmony_ci { 38662306a36Sopenharmony_ci .name = "powerdown", 38762306a36Sopenharmony_ci .read = ad5064_read_dac_powerdown, 38862306a36Sopenharmony_ci .write = ad5064_write_dac_powerdown, 38962306a36Sopenharmony_ci .shared = IIO_SEPARATE, 39062306a36Sopenharmony_ci }, 39162306a36Sopenharmony_ci IIO_ENUM("powerdown_mode", IIO_SEPARATE, <c2617_powerdown_mode_enum), 39262306a36Sopenharmony_ci IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, <c2617_powerdown_mode_enum), 39362306a36Sopenharmony_ci { }, 39462306a36Sopenharmony_ci}; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci#define AD5064_CHANNEL(chan, addr, bits, _shift, _ext_info) { \ 39762306a36Sopenharmony_ci .type = IIO_VOLTAGE, \ 39862306a36Sopenharmony_ci .indexed = 1, \ 39962306a36Sopenharmony_ci .output = 1, \ 40062306a36Sopenharmony_ci .channel = (chan), \ 40162306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 40262306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), \ 40362306a36Sopenharmony_ci .address = addr, \ 40462306a36Sopenharmony_ci .scan_type = { \ 40562306a36Sopenharmony_ci .sign = 'u', \ 40662306a36Sopenharmony_ci .realbits = (bits), \ 40762306a36Sopenharmony_ci .storagebits = 16, \ 40862306a36Sopenharmony_ci .shift = (_shift), \ 40962306a36Sopenharmony_ci }, \ 41062306a36Sopenharmony_ci .ext_info = (_ext_info), \ 41162306a36Sopenharmony_ci} 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci#define DECLARE_AD5064_CHANNELS(name, bits, shift, ext_info) \ 41462306a36Sopenharmony_ciconst struct iio_chan_spec name[] = { \ 41562306a36Sopenharmony_ci AD5064_CHANNEL(0, 0, bits, shift, ext_info), \ 41662306a36Sopenharmony_ci AD5064_CHANNEL(1, 1, bits, shift, ext_info), \ 41762306a36Sopenharmony_ci AD5064_CHANNEL(2, 2, bits, shift, ext_info), \ 41862306a36Sopenharmony_ci AD5064_CHANNEL(3, 3, bits, shift, ext_info), \ 41962306a36Sopenharmony_ci AD5064_CHANNEL(4, 4, bits, shift, ext_info), \ 42062306a36Sopenharmony_ci AD5064_CHANNEL(5, 5, bits, shift, ext_info), \ 42162306a36Sopenharmony_ci AD5064_CHANNEL(6, 6, bits, shift, ext_info), \ 42262306a36Sopenharmony_ci AD5064_CHANNEL(7, 7, bits, shift, ext_info), \ 42362306a36Sopenharmony_ci} 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci#define DECLARE_AD5065_CHANNELS(name, bits, shift, ext_info) \ 42662306a36Sopenharmony_ciconst struct iio_chan_spec name[] = { \ 42762306a36Sopenharmony_ci AD5064_CHANNEL(0, 0, bits, shift, ext_info), \ 42862306a36Sopenharmony_ci AD5064_CHANNEL(1, 3, bits, shift, ext_info), \ 42962306a36Sopenharmony_ci} 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ad5024_channels, 12, 8, ad5064_ext_info); 43262306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ad5044_channels, 14, 6, ad5064_ext_info); 43362306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ad5064_channels, 16, 4, ad5064_ext_info); 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_cistatic DECLARE_AD5065_CHANNELS(ad5025_channels, 12, 8, ad5064_ext_info); 43662306a36Sopenharmony_cistatic DECLARE_AD5065_CHANNELS(ad5045_channels, 14, 6, ad5064_ext_info); 43762306a36Sopenharmony_cistatic DECLARE_AD5065_CHANNELS(ad5065_channels, 16, 4, ad5064_ext_info); 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ad5629_channels, 12, 4, ad5064_ext_info); 44062306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ad5645_channels, 14, 2, ad5064_ext_info); 44162306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ad5669_channels, 16, 0, ad5064_ext_info); 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ltc2607_channels, 16, 0, ltc2617_ext_info); 44462306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ltc2617_channels, 14, 2, ltc2617_ext_info); 44562306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ltc2627_channels, 12, 4, ltc2617_ext_info); 44662306a36Sopenharmony_ci#define ltc2631_12_channels ltc2627_channels 44762306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ltc2631_10_channels, 10, 6, ltc2617_ext_info); 44862306a36Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ltc2631_8_channels, 8, 8, ltc2617_ext_info); 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci#define LTC2631_INFO(vref, pchannels, nchannels) \ 45162306a36Sopenharmony_ci { \ 45262306a36Sopenharmony_ci .shared_vref = true, \ 45362306a36Sopenharmony_ci .internal_vref = vref, \ 45462306a36Sopenharmony_ci .channels = pchannels, \ 45562306a36Sopenharmony_ci .num_channels = nchannels, \ 45662306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_LTC, \ 45762306a36Sopenharmony_ci } 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_cistatic const struct ad5064_chip_info ad5064_chip_info_tbl[] = { 46162306a36Sopenharmony_ci [ID_AD5024] = { 46262306a36Sopenharmony_ci .shared_vref = false, 46362306a36Sopenharmony_ci .channels = ad5024_channels, 46462306a36Sopenharmony_ci .num_channels = 4, 46562306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI, 46662306a36Sopenharmony_ci }, 46762306a36Sopenharmony_ci [ID_AD5025] = { 46862306a36Sopenharmony_ci .shared_vref = false, 46962306a36Sopenharmony_ci .channels = ad5025_channels, 47062306a36Sopenharmony_ci .num_channels = 2, 47162306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI, 47262306a36Sopenharmony_ci }, 47362306a36Sopenharmony_ci [ID_AD5044] = { 47462306a36Sopenharmony_ci .shared_vref = false, 47562306a36Sopenharmony_ci .channels = ad5044_channels, 47662306a36Sopenharmony_ci .num_channels = 4, 47762306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI, 47862306a36Sopenharmony_ci }, 47962306a36Sopenharmony_ci [ID_AD5045] = { 48062306a36Sopenharmony_ci .shared_vref = false, 48162306a36Sopenharmony_ci .channels = ad5045_channels, 48262306a36Sopenharmony_ci .num_channels = 2, 48362306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI, 48462306a36Sopenharmony_ci }, 48562306a36Sopenharmony_ci [ID_AD5064] = { 48662306a36Sopenharmony_ci .shared_vref = false, 48762306a36Sopenharmony_ci .channels = ad5064_channels, 48862306a36Sopenharmony_ci .num_channels = 4, 48962306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI, 49062306a36Sopenharmony_ci }, 49162306a36Sopenharmony_ci [ID_AD5064_1] = { 49262306a36Sopenharmony_ci .shared_vref = true, 49362306a36Sopenharmony_ci .channels = ad5064_channels, 49462306a36Sopenharmony_ci .num_channels = 4, 49562306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI, 49662306a36Sopenharmony_ci }, 49762306a36Sopenharmony_ci [ID_AD5065] = { 49862306a36Sopenharmony_ci .shared_vref = false, 49962306a36Sopenharmony_ci .channels = ad5065_channels, 50062306a36Sopenharmony_ci .num_channels = 2, 50162306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI, 50262306a36Sopenharmony_ci }, 50362306a36Sopenharmony_ci [ID_AD5625] = { 50462306a36Sopenharmony_ci .shared_vref = true, 50562306a36Sopenharmony_ci .channels = ad5629_channels, 50662306a36Sopenharmony_ci .num_channels = 4, 50762306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI2 50862306a36Sopenharmony_ci }, 50962306a36Sopenharmony_ci [ID_AD5625R_1V25] = { 51062306a36Sopenharmony_ci .shared_vref = true, 51162306a36Sopenharmony_ci .internal_vref = 1250000, 51262306a36Sopenharmony_ci .channels = ad5629_channels, 51362306a36Sopenharmony_ci .num_channels = 4, 51462306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI2 51562306a36Sopenharmony_ci }, 51662306a36Sopenharmony_ci [ID_AD5625R_2V5] = { 51762306a36Sopenharmony_ci .shared_vref = true, 51862306a36Sopenharmony_ci .internal_vref = 2500000, 51962306a36Sopenharmony_ci .channels = ad5629_channels, 52062306a36Sopenharmony_ci .num_channels = 4, 52162306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI2 52262306a36Sopenharmony_ci }, 52362306a36Sopenharmony_ci [ID_AD5627] = { 52462306a36Sopenharmony_ci .shared_vref = true, 52562306a36Sopenharmony_ci .channels = ad5629_channels, 52662306a36Sopenharmony_ci .num_channels = 2, 52762306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI2 52862306a36Sopenharmony_ci }, 52962306a36Sopenharmony_ci [ID_AD5627R_1V25] = { 53062306a36Sopenharmony_ci .shared_vref = true, 53162306a36Sopenharmony_ci .internal_vref = 1250000, 53262306a36Sopenharmony_ci .channels = ad5629_channels, 53362306a36Sopenharmony_ci .num_channels = 2, 53462306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI2 53562306a36Sopenharmony_ci }, 53662306a36Sopenharmony_ci [ID_AD5627R_2V5] = { 53762306a36Sopenharmony_ci .shared_vref = true, 53862306a36Sopenharmony_ci .internal_vref = 2500000, 53962306a36Sopenharmony_ci .channels = ad5629_channels, 54062306a36Sopenharmony_ci .num_channels = 2, 54162306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI2 54262306a36Sopenharmony_ci }, 54362306a36Sopenharmony_ci [ID_AD5628_1] = { 54462306a36Sopenharmony_ci .shared_vref = true, 54562306a36Sopenharmony_ci .internal_vref = 2500000, 54662306a36Sopenharmony_ci .channels = ad5024_channels, 54762306a36Sopenharmony_ci .num_channels = 8, 54862306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI, 54962306a36Sopenharmony_ci }, 55062306a36Sopenharmony_ci [ID_AD5628_2] = { 55162306a36Sopenharmony_ci .shared_vref = true, 55262306a36Sopenharmony_ci .internal_vref = 5000000, 55362306a36Sopenharmony_ci .channels = ad5024_channels, 55462306a36Sopenharmony_ci .num_channels = 8, 55562306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI, 55662306a36Sopenharmony_ci }, 55762306a36Sopenharmony_ci [ID_AD5629_1] = { 55862306a36Sopenharmony_ci .shared_vref = true, 55962306a36Sopenharmony_ci .internal_vref = 2500000, 56062306a36Sopenharmony_ci .channels = ad5629_channels, 56162306a36Sopenharmony_ci .num_channels = 8, 56262306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI, 56362306a36Sopenharmony_ci }, 56462306a36Sopenharmony_ci [ID_AD5629_2] = { 56562306a36Sopenharmony_ci .shared_vref = true, 56662306a36Sopenharmony_ci .internal_vref = 5000000, 56762306a36Sopenharmony_ci .channels = ad5629_channels, 56862306a36Sopenharmony_ci .num_channels = 8, 56962306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI, 57062306a36Sopenharmony_ci }, 57162306a36Sopenharmony_ci [ID_AD5645R_1V25] = { 57262306a36Sopenharmony_ci .shared_vref = true, 57362306a36Sopenharmony_ci .internal_vref = 1250000, 57462306a36Sopenharmony_ci .channels = ad5645_channels, 57562306a36Sopenharmony_ci .num_channels = 4, 57662306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI2 57762306a36Sopenharmony_ci }, 57862306a36Sopenharmony_ci [ID_AD5645R_2V5] = { 57962306a36Sopenharmony_ci .shared_vref = true, 58062306a36Sopenharmony_ci .internal_vref = 2500000, 58162306a36Sopenharmony_ci .channels = ad5645_channels, 58262306a36Sopenharmony_ci .num_channels = 4, 58362306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI2 58462306a36Sopenharmony_ci }, 58562306a36Sopenharmony_ci [ID_AD5647R_1V25] = { 58662306a36Sopenharmony_ci .shared_vref = true, 58762306a36Sopenharmony_ci .internal_vref = 1250000, 58862306a36Sopenharmony_ci .channels = ad5645_channels, 58962306a36Sopenharmony_ci .num_channels = 2, 59062306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI2 59162306a36Sopenharmony_ci }, 59262306a36Sopenharmony_ci [ID_AD5647R_2V5] = { 59362306a36Sopenharmony_ci .shared_vref = true, 59462306a36Sopenharmony_ci .internal_vref = 2500000, 59562306a36Sopenharmony_ci .channels = ad5645_channels, 59662306a36Sopenharmony_ci .num_channels = 2, 59762306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI2 59862306a36Sopenharmony_ci }, 59962306a36Sopenharmony_ci [ID_AD5648_1] = { 60062306a36Sopenharmony_ci .shared_vref = true, 60162306a36Sopenharmony_ci .internal_vref = 2500000, 60262306a36Sopenharmony_ci .channels = ad5044_channels, 60362306a36Sopenharmony_ci .num_channels = 8, 60462306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI, 60562306a36Sopenharmony_ci }, 60662306a36Sopenharmony_ci [ID_AD5648_2] = { 60762306a36Sopenharmony_ci .shared_vref = true, 60862306a36Sopenharmony_ci .internal_vref = 5000000, 60962306a36Sopenharmony_ci .channels = ad5044_channels, 61062306a36Sopenharmony_ci .num_channels = 8, 61162306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI, 61262306a36Sopenharmony_ci }, 61362306a36Sopenharmony_ci [ID_AD5665] = { 61462306a36Sopenharmony_ci .shared_vref = true, 61562306a36Sopenharmony_ci .channels = ad5669_channels, 61662306a36Sopenharmony_ci .num_channels = 4, 61762306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI2 61862306a36Sopenharmony_ci }, 61962306a36Sopenharmony_ci [ID_AD5665R_1V25] = { 62062306a36Sopenharmony_ci .shared_vref = true, 62162306a36Sopenharmony_ci .internal_vref = 1250000, 62262306a36Sopenharmony_ci .channels = ad5669_channels, 62362306a36Sopenharmony_ci .num_channels = 4, 62462306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI2 62562306a36Sopenharmony_ci }, 62662306a36Sopenharmony_ci [ID_AD5665R_2V5] = { 62762306a36Sopenharmony_ci .shared_vref = true, 62862306a36Sopenharmony_ci .internal_vref = 2500000, 62962306a36Sopenharmony_ci .channels = ad5669_channels, 63062306a36Sopenharmony_ci .num_channels = 4, 63162306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI2 63262306a36Sopenharmony_ci }, 63362306a36Sopenharmony_ci [ID_AD5666_1] = { 63462306a36Sopenharmony_ci .shared_vref = true, 63562306a36Sopenharmony_ci .internal_vref = 2500000, 63662306a36Sopenharmony_ci .channels = ad5064_channels, 63762306a36Sopenharmony_ci .num_channels = 4, 63862306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI, 63962306a36Sopenharmony_ci }, 64062306a36Sopenharmony_ci [ID_AD5666_2] = { 64162306a36Sopenharmony_ci .shared_vref = true, 64262306a36Sopenharmony_ci .internal_vref = 5000000, 64362306a36Sopenharmony_ci .channels = ad5064_channels, 64462306a36Sopenharmony_ci .num_channels = 4, 64562306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI, 64662306a36Sopenharmony_ci }, 64762306a36Sopenharmony_ci [ID_AD5667] = { 64862306a36Sopenharmony_ci .shared_vref = true, 64962306a36Sopenharmony_ci .channels = ad5669_channels, 65062306a36Sopenharmony_ci .num_channels = 2, 65162306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI2 65262306a36Sopenharmony_ci }, 65362306a36Sopenharmony_ci [ID_AD5667R_1V25] = { 65462306a36Sopenharmony_ci .shared_vref = true, 65562306a36Sopenharmony_ci .internal_vref = 1250000, 65662306a36Sopenharmony_ci .channels = ad5669_channels, 65762306a36Sopenharmony_ci .num_channels = 2, 65862306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI2 65962306a36Sopenharmony_ci }, 66062306a36Sopenharmony_ci [ID_AD5667R_2V5] = { 66162306a36Sopenharmony_ci .shared_vref = true, 66262306a36Sopenharmony_ci .internal_vref = 2500000, 66362306a36Sopenharmony_ci .channels = ad5669_channels, 66462306a36Sopenharmony_ci .num_channels = 2, 66562306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI2 66662306a36Sopenharmony_ci }, 66762306a36Sopenharmony_ci [ID_AD5668_1] = { 66862306a36Sopenharmony_ci .shared_vref = true, 66962306a36Sopenharmony_ci .internal_vref = 2500000, 67062306a36Sopenharmony_ci .channels = ad5064_channels, 67162306a36Sopenharmony_ci .num_channels = 8, 67262306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI, 67362306a36Sopenharmony_ci }, 67462306a36Sopenharmony_ci [ID_AD5668_2] = { 67562306a36Sopenharmony_ci .shared_vref = true, 67662306a36Sopenharmony_ci .internal_vref = 5000000, 67762306a36Sopenharmony_ci .channels = ad5064_channels, 67862306a36Sopenharmony_ci .num_channels = 8, 67962306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI, 68062306a36Sopenharmony_ci }, 68162306a36Sopenharmony_ci [ID_AD5669_1] = { 68262306a36Sopenharmony_ci .shared_vref = true, 68362306a36Sopenharmony_ci .internal_vref = 2500000, 68462306a36Sopenharmony_ci .channels = ad5669_channels, 68562306a36Sopenharmony_ci .num_channels = 8, 68662306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI, 68762306a36Sopenharmony_ci }, 68862306a36Sopenharmony_ci [ID_AD5669_2] = { 68962306a36Sopenharmony_ci .shared_vref = true, 69062306a36Sopenharmony_ci .internal_vref = 5000000, 69162306a36Sopenharmony_ci .channels = ad5669_channels, 69262306a36Sopenharmony_ci .num_channels = 8, 69362306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_ADI, 69462306a36Sopenharmony_ci }, 69562306a36Sopenharmony_ci [ID_LTC2606] = { 69662306a36Sopenharmony_ci .shared_vref = true, 69762306a36Sopenharmony_ci .internal_vref = 0, 69862306a36Sopenharmony_ci .channels = ltc2607_channels, 69962306a36Sopenharmony_ci .num_channels = 1, 70062306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_LTC, 70162306a36Sopenharmony_ci }, 70262306a36Sopenharmony_ci [ID_LTC2607] = { 70362306a36Sopenharmony_ci .shared_vref = true, 70462306a36Sopenharmony_ci .internal_vref = 0, 70562306a36Sopenharmony_ci .channels = ltc2607_channels, 70662306a36Sopenharmony_ci .num_channels = 2, 70762306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_LTC, 70862306a36Sopenharmony_ci }, 70962306a36Sopenharmony_ci [ID_LTC2609] = { 71062306a36Sopenharmony_ci .shared_vref = false, 71162306a36Sopenharmony_ci .internal_vref = 0, 71262306a36Sopenharmony_ci .channels = ltc2607_channels, 71362306a36Sopenharmony_ci .num_channels = 4, 71462306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_LTC, 71562306a36Sopenharmony_ci }, 71662306a36Sopenharmony_ci [ID_LTC2616] = { 71762306a36Sopenharmony_ci .shared_vref = true, 71862306a36Sopenharmony_ci .internal_vref = 0, 71962306a36Sopenharmony_ci .channels = ltc2617_channels, 72062306a36Sopenharmony_ci .num_channels = 1, 72162306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_LTC, 72262306a36Sopenharmony_ci }, 72362306a36Sopenharmony_ci [ID_LTC2617] = { 72462306a36Sopenharmony_ci .shared_vref = true, 72562306a36Sopenharmony_ci .internal_vref = 0, 72662306a36Sopenharmony_ci .channels = ltc2617_channels, 72762306a36Sopenharmony_ci .num_channels = 2, 72862306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_LTC, 72962306a36Sopenharmony_ci }, 73062306a36Sopenharmony_ci [ID_LTC2619] = { 73162306a36Sopenharmony_ci .shared_vref = false, 73262306a36Sopenharmony_ci .internal_vref = 0, 73362306a36Sopenharmony_ci .channels = ltc2617_channels, 73462306a36Sopenharmony_ci .num_channels = 4, 73562306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_LTC, 73662306a36Sopenharmony_ci }, 73762306a36Sopenharmony_ci [ID_LTC2626] = { 73862306a36Sopenharmony_ci .shared_vref = true, 73962306a36Sopenharmony_ci .internal_vref = 0, 74062306a36Sopenharmony_ci .channels = ltc2627_channels, 74162306a36Sopenharmony_ci .num_channels = 1, 74262306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_LTC, 74362306a36Sopenharmony_ci }, 74462306a36Sopenharmony_ci [ID_LTC2627] = { 74562306a36Sopenharmony_ci .shared_vref = true, 74662306a36Sopenharmony_ci .internal_vref = 0, 74762306a36Sopenharmony_ci .channels = ltc2627_channels, 74862306a36Sopenharmony_ci .num_channels = 2, 74962306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_LTC, 75062306a36Sopenharmony_ci }, 75162306a36Sopenharmony_ci [ID_LTC2629] = { 75262306a36Sopenharmony_ci .shared_vref = false, 75362306a36Sopenharmony_ci .internal_vref = 0, 75462306a36Sopenharmony_ci .channels = ltc2627_channels, 75562306a36Sopenharmony_ci .num_channels = 4, 75662306a36Sopenharmony_ci .regmap_type = AD5064_REGMAP_LTC, 75762306a36Sopenharmony_ci }, 75862306a36Sopenharmony_ci [ID_LTC2631_L12] = LTC2631_INFO(2500000, ltc2631_12_channels, 1), 75962306a36Sopenharmony_ci [ID_LTC2631_H12] = LTC2631_INFO(4096000, ltc2631_12_channels, 1), 76062306a36Sopenharmony_ci [ID_LTC2631_L10] = LTC2631_INFO(2500000, ltc2631_10_channels, 1), 76162306a36Sopenharmony_ci [ID_LTC2631_H10] = LTC2631_INFO(4096000, ltc2631_10_channels, 1), 76262306a36Sopenharmony_ci [ID_LTC2631_L8] = LTC2631_INFO(2500000, ltc2631_8_channels, 1), 76362306a36Sopenharmony_ci [ID_LTC2631_H8] = LTC2631_INFO(4096000, ltc2631_8_channels, 1), 76462306a36Sopenharmony_ci [ID_LTC2633_L12] = LTC2631_INFO(2500000, ltc2631_12_channels, 2), 76562306a36Sopenharmony_ci [ID_LTC2633_H12] = LTC2631_INFO(4096000, ltc2631_12_channels, 2), 76662306a36Sopenharmony_ci [ID_LTC2633_L10] = LTC2631_INFO(2500000, ltc2631_10_channels, 2), 76762306a36Sopenharmony_ci [ID_LTC2633_H10] = LTC2631_INFO(4096000, ltc2631_10_channels, 2), 76862306a36Sopenharmony_ci [ID_LTC2633_L8] = LTC2631_INFO(2500000, ltc2631_8_channels, 2), 76962306a36Sopenharmony_ci [ID_LTC2633_H8] = LTC2631_INFO(4096000, ltc2631_8_channels, 2), 77062306a36Sopenharmony_ci [ID_LTC2635_L12] = LTC2631_INFO(2500000, ltc2631_12_channels, 4), 77162306a36Sopenharmony_ci [ID_LTC2635_H12] = LTC2631_INFO(4096000, ltc2631_12_channels, 4), 77262306a36Sopenharmony_ci [ID_LTC2635_L10] = LTC2631_INFO(2500000, ltc2631_10_channels, 4), 77362306a36Sopenharmony_ci [ID_LTC2635_H10] = LTC2631_INFO(4096000, ltc2631_10_channels, 4), 77462306a36Sopenharmony_ci [ID_LTC2635_L8] = LTC2631_INFO(2500000, ltc2631_8_channels, 4), 77562306a36Sopenharmony_ci [ID_LTC2635_H8] = LTC2631_INFO(4096000, ltc2631_8_channels, 4), 77662306a36Sopenharmony_ci}; 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_cistatic inline unsigned int ad5064_num_vref(struct ad5064_state *st) 77962306a36Sopenharmony_ci{ 78062306a36Sopenharmony_ci return st->chip_info->shared_vref ? 1 : st->chip_info->num_channels; 78162306a36Sopenharmony_ci} 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_cistatic const char * const ad5064_vref_names[] = { 78462306a36Sopenharmony_ci "vrefA", 78562306a36Sopenharmony_ci "vrefB", 78662306a36Sopenharmony_ci "vrefC", 78762306a36Sopenharmony_ci "vrefD", 78862306a36Sopenharmony_ci}; 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_cistatic const char *ad5064_vref_name(struct ad5064_state *st, 79162306a36Sopenharmony_ci unsigned int vref) 79262306a36Sopenharmony_ci{ 79362306a36Sopenharmony_ci return st->chip_info->shared_vref ? "vref" : ad5064_vref_names[vref]; 79462306a36Sopenharmony_ci} 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_cistatic int ad5064_set_config(struct ad5064_state *st, unsigned int val) 79762306a36Sopenharmony_ci{ 79862306a36Sopenharmony_ci unsigned int cmd; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci switch (st->chip_info->regmap_type) { 80162306a36Sopenharmony_ci case AD5064_REGMAP_ADI2: 80262306a36Sopenharmony_ci cmd = AD5064_CMD_CONFIG_V2; 80362306a36Sopenharmony_ci break; 80462306a36Sopenharmony_ci default: 80562306a36Sopenharmony_ci cmd = AD5064_CMD_CONFIG; 80662306a36Sopenharmony_ci break; 80762306a36Sopenharmony_ci } 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci return ad5064_write(st, cmd, 0, val, 0); 81062306a36Sopenharmony_ci} 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_cistatic int ad5064_request_vref(struct ad5064_state *st, struct device *dev) 81362306a36Sopenharmony_ci{ 81462306a36Sopenharmony_ci unsigned int i; 81562306a36Sopenharmony_ci int ret; 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci for (i = 0; i < ad5064_num_vref(st); ++i) 81862306a36Sopenharmony_ci st->vref_reg[i].supply = ad5064_vref_name(st, i); 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci if (!st->chip_info->internal_vref) 82162306a36Sopenharmony_ci return devm_regulator_bulk_get(dev, ad5064_num_vref(st), 82262306a36Sopenharmony_ci st->vref_reg); 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci /* 82562306a36Sopenharmony_ci * This assumes that when the regulator has an internal VREF 82662306a36Sopenharmony_ci * there is only one external VREF connection, which is 82762306a36Sopenharmony_ci * currently the case for all supported devices. 82862306a36Sopenharmony_ci */ 82962306a36Sopenharmony_ci st->vref_reg[0].consumer = devm_regulator_get_optional(dev, "vref"); 83062306a36Sopenharmony_ci if (!IS_ERR(st->vref_reg[0].consumer)) 83162306a36Sopenharmony_ci return 0; 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci ret = PTR_ERR(st->vref_reg[0].consumer); 83462306a36Sopenharmony_ci if (ret != -ENODEV) 83562306a36Sopenharmony_ci return ret; 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci /* If no external regulator was supplied use the internal VREF */ 83862306a36Sopenharmony_ci st->use_internal_vref = true; 83962306a36Sopenharmony_ci ret = ad5064_set_config(st, AD5064_CONFIG_INT_VREF_ENABLE); 84062306a36Sopenharmony_ci if (ret) 84162306a36Sopenharmony_ci dev_err(dev, "Failed to enable internal vref: %d\n", ret); 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci return ret; 84462306a36Sopenharmony_ci} 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_cistatic void ad5064_bulk_reg_disable(void *data) 84762306a36Sopenharmony_ci{ 84862306a36Sopenharmony_ci struct ad5064_state *st = data; 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); 85162306a36Sopenharmony_ci} 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_cistatic int ad5064_probe(struct device *dev, enum ad5064_type type, 85462306a36Sopenharmony_ci const char *name, ad5064_write_func write) 85562306a36Sopenharmony_ci{ 85662306a36Sopenharmony_ci struct iio_dev *indio_dev; 85762306a36Sopenharmony_ci struct ad5064_state *st; 85862306a36Sopenharmony_ci unsigned int midscale; 85962306a36Sopenharmony_ci unsigned int i; 86062306a36Sopenharmony_ci int ret; 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); 86362306a36Sopenharmony_ci if (indio_dev == NULL) 86462306a36Sopenharmony_ci return -ENOMEM; 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci st = iio_priv(indio_dev); 86762306a36Sopenharmony_ci mutex_init(&st->lock); 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci st->chip_info = &ad5064_chip_info_tbl[type]; 87062306a36Sopenharmony_ci st->dev = dev; 87162306a36Sopenharmony_ci st->write = write; 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci ret = ad5064_request_vref(st, dev); 87462306a36Sopenharmony_ci if (ret) 87562306a36Sopenharmony_ci return ret; 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci if (!st->use_internal_vref) { 87862306a36Sopenharmony_ci ret = regulator_bulk_enable(ad5064_num_vref(st), st->vref_reg); 87962306a36Sopenharmony_ci if (ret) 88062306a36Sopenharmony_ci return ret; 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci ret = devm_add_action_or_reset(dev, ad5064_bulk_reg_disable, st); 88362306a36Sopenharmony_ci if (ret) 88462306a36Sopenharmony_ci return ret; 88562306a36Sopenharmony_ci } 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci indio_dev->name = name; 88862306a36Sopenharmony_ci indio_dev->info = &ad5064_info; 88962306a36Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE; 89062306a36Sopenharmony_ci indio_dev->channels = st->chip_info->channels; 89162306a36Sopenharmony_ci indio_dev->num_channels = st->chip_info->num_channels; 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci midscale = (1 << indio_dev->channels[0].scan_type.realbits) / 2; 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci for (i = 0; i < st->chip_info->num_channels; ++i) { 89662306a36Sopenharmony_ci st->pwr_down_mode[i] = AD5064_LDAC_PWRDN_1K; 89762306a36Sopenharmony_ci st->dac_cache[i] = midscale; 89862306a36Sopenharmony_ci } 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci return devm_iio_device_register(dev, indio_dev); 90162306a36Sopenharmony_ci} 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_SPI_MASTER) 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_cistatic int ad5064_spi_write(struct ad5064_state *st, unsigned int cmd, 90662306a36Sopenharmony_ci unsigned int addr, unsigned int val) 90762306a36Sopenharmony_ci{ 90862306a36Sopenharmony_ci struct spi_device *spi = to_spi_device(st->dev); 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci st->data.spi = cpu_to_be32(AD5064_CMD(cmd) | AD5064_ADDR(addr) | val); 91162306a36Sopenharmony_ci return spi_write(spi, &st->data.spi, sizeof(st->data.spi)); 91262306a36Sopenharmony_ci} 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_cistatic int ad5064_spi_probe(struct spi_device *spi) 91562306a36Sopenharmony_ci{ 91662306a36Sopenharmony_ci const struct spi_device_id *id = spi_get_device_id(spi); 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci return ad5064_probe(&spi->dev, id->driver_data, id->name, 91962306a36Sopenharmony_ci ad5064_spi_write); 92062306a36Sopenharmony_ci} 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_cistatic const struct spi_device_id ad5064_spi_ids[] = { 92362306a36Sopenharmony_ci {"ad5024", ID_AD5024}, 92462306a36Sopenharmony_ci {"ad5025", ID_AD5025}, 92562306a36Sopenharmony_ci {"ad5044", ID_AD5044}, 92662306a36Sopenharmony_ci {"ad5045", ID_AD5045}, 92762306a36Sopenharmony_ci {"ad5064", ID_AD5064}, 92862306a36Sopenharmony_ci {"ad5064-1", ID_AD5064_1}, 92962306a36Sopenharmony_ci {"ad5065", ID_AD5065}, 93062306a36Sopenharmony_ci {"ad5628-1", ID_AD5628_1}, 93162306a36Sopenharmony_ci {"ad5628-2", ID_AD5628_2}, 93262306a36Sopenharmony_ci {"ad5648-1", ID_AD5648_1}, 93362306a36Sopenharmony_ci {"ad5648-2", ID_AD5648_2}, 93462306a36Sopenharmony_ci {"ad5666-1", ID_AD5666_1}, 93562306a36Sopenharmony_ci {"ad5666-2", ID_AD5666_2}, 93662306a36Sopenharmony_ci {"ad5668-1", ID_AD5668_1}, 93762306a36Sopenharmony_ci {"ad5668-2", ID_AD5668_2}, 93862306a36Sopenharmony_ci {"ad5668-3", ID_AD5668_2}, /* similar enough to ad5668-2 */ 93962306a36Sopenharmony_ci {} 94062306a36Sopenharmony_ci}; 94162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, ad5064_spi_ids); 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_cistatic struct spi_driver ad5064_spi_driver = { 94462306a36Sopenharmony_ci .driver = { 94562306a36Sopenharmony_ci .name = "ad5064", 94662306a36Sopenharmony_ci }, 94762306a36Sopenharmony_ci .probe = ad5064_spi_probe, 94862306a36Sopenharmony_ci .id_table = ad5064_spi_ids, 94962306a36Sopenharmony_ci}; 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_cistatic int __init ad5064_spi_register_driver(void) 95262306a36Sopenharmony_ci{ 95362306a36Sopenharmony_ci return spi_register_driver(&ad5064_spi_driver); 95462306a36Sopenharmony_ci} 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_cistatic void ad5064_spi_unregister_driver(void) 95762306a36Sopenharmony_ci{ 95862306a36Sopenharmony_ci spi_unregister_driver(&ad5064_spi_driver); 95962306a36Sopenharmony_ci} 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci#else 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_cistatic inline int ad5064_spi_register_driver(void) { return 0; } 96462306a36Sopenharmony_cistatic inline void ad5064_spi_unregister_driver(void) { } 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci#endif 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_I2C) 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_cistatic int ad5064_i2c_write(struct ad5064_state *st, unsigned int cmd, 97162306a36Sopenharmony_ci unsigned int addr, unsigned int val) 97262306a36Sopenharmony_ci{ 97362306a36Sopenharmony_ci struct i2c_client *i2c = to_i2c_client(st->dev); 97462306a36Sopenharmony_ci unsigned int cmd_shift; 97562306a36Sopenharmony_ci int ret; 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci switch (st->chip_info->regmap_type) { 97862306a36Sopenharmony_ci case AD5064_REGMAP_ADI2: 97962306a36Sopenharmony_ci cmd_shift = 3; 98062306a36Sopenharmony_ci break; 98162306a36Sopenharmony_ci default: 98262306a36Sopenharmony_ci cmd_shift = 4; 98362306a36Sopenharmony_ci break; 98462306a36Sopenharmony_ci } 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci st->data.i2c[0] = (cmd << cmd_shift) | addr; 98762306a36Sopenharmony_ci put_unaligned_be16(val, &st->data.i2c[1]); 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_ci ret = i2c_master_send(i2c, st->data.i2c, 3); 99062306a36Sopenharmony_ci if (ret < 0) 99162306a36Sopenharmony_ci return ret; 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci return 0; 99462306a36Sopenharmony_ci} 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_cistatic int ad5064_i2c_probe(struct i2c_client *i2c) 99762306a36Sopenharmony_ci{ 99862306a36Sopenharmony_ci const struct i2c_device_id *id = i2c_client_get_device_id(i2c); 99962306a36Sopenharmony_ci return ad5064_probe(&i2c->dev, id->driver_data, id->name, 100062306a36Sopenharmony_ci ad5064_i2c_write); 100162306a36Sopenharmony_ci} 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_cistatic const struct i2c_device_id ad5064_i2c_ids[] = { 100462306a36Sopenharmony_ci {"ad5625", ID_AD5625 }, 100562306a36Sopenharmony_ci {"ad5625r-1v25", ID_AD5625R_1V25 }, 100662306a36Sopenharmony_ci {"ad5625r-2v5", ID_AD5625R_2V5 }, 100762306a36Sopenharmony_ci {"ad5627", ID_AD5627 }, 100862306a36Sopenharmony_ci {"ad5627r-1v25", ID_AD5627R_1V25 }, 100962306a36Sopenharmony_ci {"ad5627r-2v5", ID_AD5627R_2V5 }, 101062306a36Sopenharmony_ci {"ad5629-1", ID_AD5629_1}, 101162306a36Sopenharmony_ci {"ad5629-2", ID_AD5629_2}, 101262306a36Sopenharmony_ci {"ad5629-3", ID_AD5629_2}, /* similar enough to ad5629-2 */ 101362306a36Sopenharmony_ci {"ad5645r-1v25", ID_AD5645R_1V25 }, 101462306a36Sopenharmony_ci {"ad5645r-2v5", ID_AD5645R_2V5 }, 101562306a36Sopenharmony_ci {"ad5665", ID_AD5665 }, 101662306a36Sopenharmony_ci {"ad5665r-1v25", ID_AD5665R_1V25 }, 101762306a36Sopenharmony_ci {"ad5665r-2v5", ID_AD5665R_2V5 }, 101862306a36Sopenharmony_ci {"ad5667", ID_AD5667 }, 101962306a36Sopenharmony_ci {"ad5667r-1v25", ID_AD5667R_1V25 }, 102062306a36Sopenharmony_ci {"ad5667r-2v5", ID_AD5667R_2V5 }, 102162306a36Sopenharmony_ci {"ad5669-1", ID_AD5669_1}, 102262306a36Sopenharmony_ci {"ad5669-2", ID_AD5669_2}, 102362306a36Sopenharmony_ci {"ad5669-3", ID_AD5669_2}, /* similar enough to ad5669-2 */ 102462306a36Sopenharmony_ci {"ltc2606", ID_LTC2606}, 102562306a36Sopenharmony_ci {"ltc2607", ID_LTC2607}, 102662306a36Sopenharmony_ci {"ltc2609", ID_LTC2609}, 102762306a36Sopenharmony_ci {"ltc2616", ID_LTC2616}, 102862306a36Sopenharmony_ci {"ltc2617", ID_LTC2617}, 102962306a36Sopenharmony_ci {"ltc2619", ID_LTC2619}, 103062306a36Sopenharmony_ci {"ltc2626", ID_LTC2626}, 103162306a36Sopenharmony_ci {"ltc2627", ID_LTC2627}, 103262306a36Sopenharmony_ci {"ltc2629", ID_LTC2629}, 103362306a36Sopenharmony_ci {"ltc2631-l12", ID_LTC2631_L12}, 103462306a36Sopenharmony_ci {"ltc2631-h12", ID_LTC2631_H12}, 103562306a36Sopenharmony_ci {"ltc2631-l10", ID_LTC2631_L10}, 103662306a36Sopenharmony_ci {"ltc2631-h10", ID_LTC2631_H10}, 103762306a36Sopenharmony_ci {"ltc2631-l8", ID_LTC2631_L8}, 103862306a36Sopenharmony_ci {"ltc2631-h8", ID_LTC2631_H8}, 103962306a36Sopenharmony_ci {"ltc2633-l12", ID_LTC2633_L12}, 104062306a36Sopenharmony_ci {"ltc2633-h12", ID_LTC2633_H12}, 104162306a36Sopenharmony_ci {"ltc2633-l10", ID_LTC2633_L10}, 104262306a36Sopenharmony_ci {"ltc2633-h10", ID_LTC2633_H10}, 104362306a36Sopenharmony_ci {"ltc2633-l8", ID_LTC2633_L8}, 104462306a36Sopenharmony_ci {"ltc2633-h8", ID_LTC2633_H8}, 104562306a36Sopenharmony_ci {"ltc2635-l12", ID_LTC2635_L12}, 104662306a36Sopenharmony_ci {"ltc2635-h12", ID_LTC2635_H12}, 104762306a36Sopenharmony_ci {"ltc2635-l10", ID_LTC2635_L10}, 104862306a36Sopenharmony_ci {"ltc2635-h10", ID_LTC2635_H10}, 104962306a36Sopenharmony_ci {"ltc2635-l8", ID_LTC2635_L8}, 105062306a36Sopenharmony_ci {"ltc2635-h8", ID_LTC2635_H8}, 105162306a36Sopenharmony_ci {} 105262306a36Sopenharmony_ci}; 105362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, ad5064_i2c_ids); 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_cistatic struct i2c_driver ad5064_i2c_driver = { 105662306a36Sopenharmony_ci .driver = { 105762306a36Sopenharmony_ci .name = "ad5064", 105862306a36Sopenharmony_ci }, 105962306a36Sopenharmony_ci .probe = ad5064_i2c_probe, 106062306a36Sopenharmony_ci .id_table = ad5064_i2c_ids, 106162306a36Sopenharmony_ci}; 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_cistatic int __init ad5064_i2c_register_driver(void) 106462306a36Sopenharmony_ci{ 106562306a36Sopenharmony_ci return i2c_add_driver(&ad5064_i2c_driver); 106662306a36Sopenharmony_ci} 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_cistatic void __exit ad5064_i2c_unregister_driver(void) 106962306a36Sopenharmony_ci{ 107062306a36Sopenharmony_ci i2c_del_driver(&ad5064_i2c_driver); 107162306a36Sopenharmony_ci} 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci#else 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_cistatic inline int ad5064_i2c_register_driver(void) { return 0; } 107662306a36Sopenharmony_cistatic inline void ad5064_i2c_unregister_driver(void) { } 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci#endif 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_cistatic int __init ad5064_init(void) 108162306a36Sopenharmony_ci{ 108262306a36Sopenharmony_ci int ret; 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci ret = ad5064_spi_register_driver(); 108562306a36Sopenharmony_ci if (ret) 108662306a36Sopenharmony_ci return ret; 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci ret = ad5064_i2c_register_driver(); 108962306a36Sopenharmony_ci if (ret) { 109062306a36Sopenharmony_ci ad5064_spi_unregister_driver(); 109162306a36Sopenharmony_ci return ret; 109262306a36Sopenharmony_ci } 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci return 0; 109562306a36Sopenharmony_ci} 109662306a36Sopenharmony_cimodule_init(ad5064_init); 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_cistatic void __exit ad5064_exit(void) 109962306a36Sopenharmony_ci{ 110062306a36Sopenharmony_ci ad5064_i2c_unregister_driver(); 110162306a36Sopenharmony_ci ad5064_spi_unregister_driver(); 110262306a36Sopenharmony_ci} 110362306a36Sopenharmony_cimodule_exit(ad5064_exit); 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ciMODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 110662306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices AD5024 and similar multi-channel DACs"); 110762306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 1108