162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * ADA4250 driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2022 Analog Devices Inc. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/bitfield.h> 962306a36Sopenharmony_ci#include <linux/bits.h> 1062306a36Sopenharmony_ci#include <linux/device.h> 1162306a36Sopenharmony_ci#include <linux/iio/iio.h> 1262306a36Sopenharmony_ci#include <linux/module.h> 1362306a36Sopenharmony_ci#include <linux/regmap.h> 1462306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 1562306a36Sopenharmony_ci#include <linux/spi/spi.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <asm/unaligned.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* ADA4250 Register Map */ 2062306a36Sopenharmony_ci#define ADA4250_REG_GAIN_MUX 0x00 2162306a36Sopenharmony_ci#define ADA4250_REG_REFBUF_EN 0x01 2262306a36Sopenharmony_ci#define ADA4250_REG_RESET 0x02 2362306a36Sopenharmony_ci#define ADA4250_REG_SNSR_CAL_VAL 0x04 2462306a36Sopenharmony_ci#define ADA4250_REG_SNSR_CAL_CNFG 0x05 2562306a36Sopenharmony_ci#define ADA4250_REG_DIE_REV 0x18 2662306a36Sopenharmony_ci#define ADA4250_REG_CHIP_ID 0x19 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci/* ADA4250_REG_GAIN_MUX Map */ 2962306a36Sopenharmony_ci#define ADA4250_GAIN_MUX_MSK GENMASK(2, 0) 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci/* ADA4250_REG_REFBUF Map */ 3262306a36Sopenharmony_ci#define ADA4250_REFBUF_MSK BIT(0) 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/* ADA4250_REG_RESET Map */ 3562306a36Sopenharmony_ci#define ADA4250_RESET_MSK BIT(0) 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* ADA4250_REG_SNSR_CAL_VAL Map */ 3862306a36Sopenharmony_ci#define ADA4250_CAL_CFG_BIAS_MSK GENMASK(7, 0) 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/* ADA4250_REG_SNSR_CAL_CNFG Bit Definition */ 4162306a36Sopenharmony_ci#define ADA4250_BIAS_SET_MSK GENMASK(3, 2) 4262306a36Sopenharmony_ci#define ADA4250_RANGE_SET_MSK GENMASK(1, 0) 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci/* Miscellaneous definitions */ 4562306a36Sopenharmony_ci#define ADA4250_CHIP_ID 0x4250 4662306a36Sopenharmony_ci#define ADA4250_RANGE1 0 4762306a36Sopenharmony_ci#define ADA4250_RANGE4 3 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/* ADA4250 current bias set */ 5062306a36Sopenharmony_cienum ada4250_current_bias { 5162306a36Sopenharmony_ci ADA4250_BIAS_DISABLED, 5262306a36Sopenharmony_ci ADA4250_BIAS_BANDGAP, 5362306a36Sopenharmony_ci ADA4250_BIAS_AVDD, 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistruct ada4250_state { 5762306a36Sopenharmony_ci struct spi_device *spi; 5862306a36Sopenharmony_ci struct regmap *regmap; 5962306a36Sopenharmony_ci struct regulator *reg; 6062306a36Sopenharmony_ci /* Protect against concurrent accesses to the device and data content */ 6162306a36Sopenharmony_ci struct mutex lock; 6262306a36Sopenharmony_ci u8 bias; 6362306a36Sopenharmony_ci u8 gain; 6462306a36Sopenharmony_ci int offset_uv; 6562306a36Sopenharmony_ci bool refbuf_en; 6662306a36Sopenharmony_ci}; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/* ADA4250 Current Bias Source Settings: Disabled, Bandgap Reference, AVDD */ 6962306a36Sopenharmony_cistatic const int calibbias_table[] = {0, 1, 2}; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/* ADA4250 Gain (V/V) values: 1, 2, 4, 8, 16, 32, 64, 128 */ 7262306a36Sopenharmony_cistatic const int hwgain_table[] = {1, 2, 4, 8, 16, 32, 64, 128}; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic const struct regmap_config ada4250_regmap_config = { 7562306a36Sopenharmony_ci .reg_bits = 8, 7662306a36Sopenharmony_ci .val_bits = 8, 7762306a36Sopenharmony_ci .read_flag_mask = BIT(7), 7862306a36Sopenharmony_ci .max_register = 0x1A, 7962306a36Sopenharmony_ci}; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic int ada4250_set_offset_uv(struct iio_dev *indio_dev, 8262306a36Sopenharmony_ci const struct iio_chan_spec *chan, 8362306a36Sopenharmony_ci int offset_uv) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci struct ada4250_state *st = iio_priv(indio_dev); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci int i, ret, x[8], max_vos, min_vos, voltage_v, vlsb = 0; 8862306a36Sopenharmony_ci u8 offset_raw, range = ADA4250_RANGE1; 8962306a36Sopenharmony_ci u32 lsb_coeff[6] = {1333, 2301, 4283, 8289, 16311, 31599}; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci if (st->bias == 0 || st->bias == 3) 9262306a36Sopenharmony_ci return -EINVAL; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci voltage_v = regulator_get_voltage(st->reg); 9562306a36Sopenharmony_ci voltage_v = DIV_ROUND_CLOSEST(voltage_v, 1000000); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci if (st->bias == ADA4250_BIAS_AVDD) 9862306a36Sopenharmony_ci x[0] = voltage_v; 9962306a36Sopenharmony_ci else 10062306a36Sopenharmony_ci x[0] = 5; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci x[1] = 126 * (x[0] - 1); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci for (i = 0; i < 6; i++) 10562306a36Sopenharmony_ci x[i + 2] = DIV_ROUND_CLOSEST(x[1] * 1000, lsb_coeff[i]); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci if (st->gain == 0) 10862306a36Sopenharmony_ci return -EINVAL; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci /* 11162306a36Sopenharmony_ci * Compute Range and Voltage per LSB for the Sensor Offset Calibration 11262306a36Sopenharmony_ci * Example of computation for Range 1 and Range 2 (Curren Bias Set = AVDD): 11362306a36Sopenharmony_ci * Range 1 Range 2 11462306a36Sopenharmony_ci * Gain | Max Vos(mV) | LSB(mV) | Max Vos(mV) | LSB(mV) | 11562306a36Sopenharmony_ci * 2 | X1*127 | X1=0.126(AVDD-1) | X1*3*127 | X1*3 | 11662306a36Sopenharmony_ci * 4 | X2*127 | X2=X1/1.3333 | X2*3*127 | X2*3 | 11762306a36Sopenharmony_ci * 8 | X3*127 | X3=X1/2.301 | X3*3*127 | X3*3 | 11862306a36Sopenharmony_ci * 16 | X4*127 | X4=X1/4.283 | X4*3*127 | X4*3 | 11962306a36Sopenharmony_ci * 32 | X5*127 | X5=X1/8.289 | X5*3*127 | X5*3 | 12062306a36Sopenharmony_ci * 64 | X6*127 | X6=X1/16.311 | X6*3*127 | X6*3 | 12162306a36Sopenharmony_ci * 128 | X7*127 | X7=X1/31.599 | X7*3*127 | X7*3 | 12262306a36Sopenharmony_ci */ 12362306a36Sopenharmony_ci for (i = ADA4250_RANGE1; i <= ADA4250_RANGE4; i++) { 12462306a36Sopenharmony_ci max_vos = x[st->gain] * 127 * ((1 << (i + 1)) - 1); 12562306a36Sopenharmony_ci min_vos = -1 * max_vos; 12662306a36Sopenharmony_ci if (offset_uv > min_vos && offset_uv < max_vos) { 12762306a36Sopenharmony_ci range = i; 12862306a36Sopenharmony_ci vlsb = x[st->gain] * ((1 << (i + 1)) - 1); 12962306a36Sopenharmony_ci break; 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci } 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci if (vlsb <= 0) 13462306a36Sopenharmony_ci return -EINVAL; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci offset_raw = DIV_ROUND_CLOSEST(abs(offset_uv), vlsb); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci mutex_lock(&st->lock); 13962306a36Sopenharmony_ci ret = regmap_update_bits(st->regmap, ADA4250_REG_SNSR_CAL_CNFG, 14062306a36Sopenharmony_ci ADA4250_RANGE_SET_MSK, 14162306a36Sopenharmony_ci FIELD_PREP(ADA4250_RANGE_SET_MSK, range)); 14262306a36Sopenharmony_ci if (ret) 14362306a36Sopenharmony_ci goto exit; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci st->offset_uv = offset_raw * vlsb; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci /* 14862306a36Sopenharmony_ci * To set the offset calibration value, use bits [6:0] and bit 7 as the 14962306a36Sopenharmony_ci * polarity bit (set to "0" for a negative offset and "1" for a positive 15062306a36Sopenharmony_ci * offset). 15162306a36Sopenharmony_ci */ 15262306a36Sopenharmony_ci if (offset_uv < 0) { 15362306a36Sopenharmony_ci offset_raw |= BIT(7); 15462306a36Sopenharmony_ci st->offset_uv *= (-1); 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci ret = regmap_write(st->regmap, ADA4250_REG_SNSR_CAL_VAL, offset_raw); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ciexit: 16062306a36Sopenharmony_ci mutex_unlock(&st->lock); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci return ret; 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistatic int ada4250_read_raw(struct iio_dev *indio_dev, 16662306a36Sopenharmony_ci struct iio_chan_spec const *chan, 16762306a36Sopenharmony_ci int *val, int *val2, long info) 16862306a36Sopenharmony_ci{ 16962306a36Sopenharmony_ci struct ada4250_state *st = iio_priv(indio_dev); 17062306a36Sopenharmony_ci int ret; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci switch (info) { 17362306a36Sopenharmony_ci case IIO_CHAN_INFO_HARDWAREGAIN: 17462306a36Sopenharmony_ci ret = regmap_read(st->regmap, ADA4250_REG_GAIN_MUX, val); 17562306a36Sopenharmony_ci if (ret) 17662306a36Sopenharmony_ci return ret; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci *val = BIT(*val); 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci return IIO_VAL_INT; 18162306a36Sopenharmony_ci case IIO_CHAN_INFO_OFFSET: 18262306a36Sopenharmony_ci *val = st->offset_uv; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci return IIO_VAL_INT; 18562306a36Sopenharmony_ci case IIO_CHAN_INFO_CALIBBIAS: 18662306a36Sopenharmony_ci ret = regmap_read(st->regmap, ADA4250_REG_SNSR_CAL_CNFG, val); 18762306a36Sopenharmony_ci if (ret) 18862306a36Sopenharmony_ci return ret; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci *val = FIELD_GET(ADA4250_BIAS_SET_MSK, *val); 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci return IIO_VAL_INT; 19362306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 19462306a36Sopenharmony_ci *val = 1; 19562306a36Sopenharmony_ci *val2 = 1000000; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL; 19862306a36Sopenharmony_ci default: 19962306a36Sopenharmony_ci return -EINVAL; 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_cistatic int ada4250_write_raw(struct iio_dev *indio_dev, 20462306a36Sopenharmony_ci struct iio_chan_spec const *chan, 20562306a36Sopenharmony_ci int val, int val2, long info) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci struct ada4250_state *st = iio_priv(indio_dev); 20862306a36Sopenharmony_ci int ret; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci switch (info) { 21162306a36Sopenharmony_ci case IIO_CHAN_INFO_HARDWAREGAIN: 21262306a36Sopenharmony_ci ret = regmap_write(st->regmap, ADA4250_REG_GAIN_MUX, 21362306a36Sopenharmony_ci FIELD_PREP(ADA4250_GAIN_MUX_MSK, ilog2(val))); 21462306a36Sopenharmony_ci if (ret) 21562306a36Sopenharmony_ci return ret; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci st->gain = ilog2(val); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci return ret; 22062306a36Sopenharmony_ci case IIO_CHAN_INFO_OFFSET: 22162306a36Sopenharmony_ci return ada4250_set_offset_uv(indio_dev, chan, val); 22262306a36Sopenharmony_ci case IIO_CHAN_INFO_CALIBBIAS: 22362306a36Sopenharmony_ci ret = regmap_update_bits(st->regmap, ADA4250_REG_SNSR_CAL_CNFG, 22462306a36Sopenharmony_ci ADA4250_BIAS_SET_MSK, 22562306a36Sopenharmony_ci FIELD_PREP(ADA4250_BIAS_SET_MSK, val)); 22662306a36Sopenharmony_ci if (ret) 22762306a36Sopenharmony_ci return ret; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci st->bias = val; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci return ret; 23262306a36Sopenharmony_ci default: 23362306a36Sopenharmony_ci return -EINVAL; 23462306a36Sopenharmony_ci } 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_cistatic int ada4250_read_avail(struct iio_dev *indio_dev, 23862306a36Sopenharmony_ci struct iio_chan_spec const *chan, 23962306a36Sopenharmony_ci const int **vals, int *type, int *length, 24062306a36Sopenharmony_ci long mask) 24162306a36Sopenharmony_ci{ 24262306a36Sopenharmony_ci switch (mask) { 24362306a36Sopenharmony_ci case IIO_CHAN_INFO_CALIBBIAS: 24462306a36Sopenharmony_ci *vals = calibbias_table; 24562306a36Sopenharmony_ci *type = IIO_VAL_INT; 24662306a36Sopenharmony_ci *length = ARRAY_SIZE(calibbias_table); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci return IIO_AVAIL_LIST; 24962306a36Sopenharmony_ci case IIO_CHAN_INFO_HARDWAREGAIN: 25062306a36Sopenharmony_ci *vals = hwgain_table; 25162306a36Sopenharmony_ci *type = IIO_VAL_INT; 25262306a36Sopenharmony_ci *length = ARRAY_SIZE(hwgain_table); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci return IIO_AVAIL_LIST; 25562306a36Sopenharmony_ci default: 25662306a36Sopenharmony_ci return -EINVAL; 25762306a36Sopenharmony_ci } 25862306a36Sopenharmony_ci} 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_cistatic int ada4250_reg_access(struct iio_dev *indio_dev, 26162306a36Sopenharmony_ci unsigned int reg, 26262306a36Sopenharmony_ci unsigned int write_val, 26362306a36Sopenharmony_ci unsigned int *read_val) 26462306a36Sopenharmony_ci{ 26562306a36Sopenharmony_ci struct ada4250_state *st = iio_priv(indio_dev); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci if (read_val) 26862306a36Sopenharmony_ci return regmap_read(st->regmap, reg, read_val); 26962306a36Sopenharmony_ci else 27062306a36Sopenharmony_ci return regmap_write(st->regmap, reg, write_val); 27162306a36Sopenharmony_ci} 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_cistatic const struct iio_info ada4250_info = { 27462306a36Sopenharmony_ci .read_raw = ada4250_read_raw, 27562306a36Sopenharmony_ci .write_raw = ada4250_write_raw, 27662306a36Sopenharmony_ci .read_avail = &ada4250_read_avail, 27762306a36Sopenharmony_ci .debugfs_reg_access = &ada4250_reg_access, 27862306a36Sopenharmony_ci}; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cistatic const struct iio_chan_spec ada4250_channels[] = { 28162306a36Sopenharmony_ci { 28262306a36Sopenharmony_ci .type = IIO_VOLTAGE, 28362306a36Sopenharmony_ci .output = 1, 28462306a36Sopenharmony_ci .indexed = 1, 28562306a36Sopenharmony_ci .channel = 0, 28662306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_HARDWAREGAIN) | 28762306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_OFFSET) | 28862306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_CALIBBIAS) | 28962306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), 29062306a36Sopenharmony_ci .info_mask_separate_available = BIT(IIO_CHAN_INFO_CALIBBIAS) | 29162306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_HARDWAREGAIN), 29262306a36Sopenharmony_ci } 29362306a36Sopenharmony_ci}; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cistatic void ada4250_reg_disable(void *data) 29662306a36Sopenharmony_ci{ 29762306a36Sopenharmony_ci regulator_disable(data); 29862306a36Sopenharmony_ci} 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_cistatic int ada4250_init(struct ada4250_state *st) 30162306a36Sopenharmony_ci{ 30262306a36Sopenharmony_ci int ret; 30362306a36Sopenharmony_ci u16 chip_id; 30462306a36Sopenharmony_ci u8 data[2] __aligned(8) = {}; 30562306a36Sopenharmony_ci struct spi_device *spi = st->spi; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci st->refbuf_en = device_property_read_bool(&spi->dev, "adi,refbuf-enable"); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci st->reg = devm_regulator_get(&spi->dev, "avdd"); 31062306a36Sopenharmony_ci if (IS_ERR(st->reg)) 31162306a36Sopenharmony_ci return dev_err_probe(&spi->dev, PTR_ERR(st->reg), 31262306a36Sopenharmony_ci "failed to get the AVDD voltage\n"); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci ret = regulator_enable(st->reg); 31562306a36Sopenharmony_ci if (ret) { 31662306a36Sopenharmony_ci dev_err(&spi->dev, "Failed to enable specified AVDD supply\n"); 31762306a36Sopenharmony_ci return ret; 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci ret = devm_add_action_or_reset(&spi->dev, ada4250_reg_disable, st->reg); 32162306a36Sopenharmony_ci if (ret) 32262306a36Sopenharmony_ci return ret; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci ret = regmap_write(st->regmap, ADA4250_REG_RESET, 32562306a36Sopenharmony_ci FIELD_PREP(ADA4250_RESET_MSK, 1)); 32662306a36Sopenharmony_ci if (ret) 32762306a36Sopenharmony_ci return ret; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci ret = regmap_bulk_read(st->regmap, ADA4250_REG_CHIP_ID, data, 2); 33062306a36Sopenharmony_ci if (ret) 33162306a36Sopenharmony_ci return ret; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci chip_id = get_unaligned_le16(data); 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci if (chip_id != ADA4250_CHIP_ID) { 33662306a36Sopenharmony_ci dev_err(&spi->dev, "Invalid chip ID.\n"); 33762306a36Sopenharmony_ci return -EINVAL; 33862306a36Sopenharmony_ci } 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci return regmap_write(st->regmap, ADA4250_REG_REFBUF_EN, 34162306a36Sopenharmony_ci FIELD_PREP(ADA4250_REFBUF_MSK, st->refbuf_en)); 34262306a36Sopenharmony_ci} 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cistatic int ada4250_probe(struct spi_device *spi) 34562306a36Sopenharmony_ci{ 34662306a36Sopenharmony_ci struct iio_dev *indio_dev; 34762306a36Sopenharmony_ci struct regmap *regmap; 34862306a36Sopenharmony_ci struct ada4250_state *st; 34962306a36Sopenharmony_ci int ret; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 35262306a36Sopenharmony_ci if (!indio_dev) 35362306a36Sopenharmony_ci return -ENOMEM; 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci regmap = devm_regmap_init_spi(spi, &ada4250_regmap_config); 35662306a36Sopenharmony_ci if (IS_ERR(regmap)) 35762306a36Sopenharmony_ci return PTR_ERR(regmap); 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci st = iio_priv(indio_dev); 36062306a36Sopenharmony_ci st->regmap = regmap; 36162306a36Sopenharmony_ci st->spi = spi; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci indio_dev->info = &ada4250_info; 36462306a36Sopenharmony_ci indio_dev->name = "ada4250"; 36562306a36Sopenharmony_ci indio_dev->channels = ada4250_channels; 36662306a36Sopenharmony_ci indio_dev->num_channels = ARRAY_SIZE(ada4250_channels); 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci mutex_init(&st->lock); 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci ret = ada4250_init(st); 37162306a36Sopenharmony_ci if (ret) { 37262306a36Sopenharmony_ci dev_err(&spi->dev, "ADA4250 init failed\n"); 37362306a36Sopenharmony_ci return ret; 37462306a36Sopenharmony_ci } 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci return devm_iio_device_register(&spi->dev, indio_dev); 37762306a36Sopenharmony_ci} 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_cistatic const struct spi_device_id ada4250_id[] = { 38062306a36Sopenharmony_ci { "ada4250", 0 }, 38162306a36Sopenharmony_ci {} 38262306a36Sopenharmony_ci}; 38362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, ada4250_id); 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_cistatic const struct of_device_id ada4250_of_match[] = { 38662306a36Sopenharmony_ci { .compatible = "adi,ada4250" }, 38762306a36Sopenharmony_ci {}, 38862306a36Sopenharmony_ci}; 38962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, ada4250_of_match); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_cistatic struct spi_driver ada4250_driver = { 39262306a36Sopenharmony_ci .driver = { 39362306a36Sopenharmony_ci .name = "ada4250", 39462306a36Sopenharmony_ci .of_match_table = ada4250_of_match, 39562306a36Sopenharmony_ci }, 39662306a36Sopenharmony_ci .probe = ada4250_probe, 39762306a36Sopenharmony_ci .id_table = ada4250_id, 39862306a36Sopenharmony_ci}; 39962306a36Sopenharmony_cimodule_spi_driver(ada4250_driver); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ciMODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com"); 40262306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices ADA4250"); 40362306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 404