ada4250.c (10044B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * ADA4250 driver 4 * 5 * Copyright 2022 Analog Devices Inc. 6 */ 7 8#include <linux/bitfield.h> 9#include <linux/bits.h> 10#include <linux/device.h> 11#include <linux/iio/iio.h> 12#include <linux/module.h> 13#include <linux/regmap.h> 14#include <linux/regulator/consumer.h> 15#include <linux/spi/spi.h> 16 17#include <asm/unaligned.h> 18 19/* ADA4250 Register Map */ 20#define ADA4250_REG_GAIN_MUX 0x00 21#define ADA4250_REG_REFBUF_EN 0x01 22#define ADA4250_REG_RESET 0x02 23#define ADA4250_REG_SNSR_CAL_VAL 0x04 24#define ADA4250_REG_SNSR_CAL_CNFG 0x05 25#define ADA4250_REG_DIE_REV 0x18 26#define ADA4250_REG_CHIP_ID 0x19 27 28/* ADA4250_REG_GAIN_MUX Map */ 29#define ADA4250_GAIN_MUX_MSK GENMASK(2, 0) 30 31/* ADA4250_REG_REFBUF Map */ 32#define ADA4250_REFBUF_MSK BIT(0) 33 34/* ADA4250_REG_RESET Map */ 35#define ADA4250_RESET_MSK BIT(0) 36 37/* ADA4250_REG_SNSR_CAL_VAL Map */ 38#define ADA4250_CAL_CFG_BIAS_MSK GENMASK(7, 0) 39 40/* ADA4250_REG_SNSR_CAL_CNFG Bit Definition */ 41#define ADA4250_BIAS_SET_MSK GENMASK(3, 2) 42#define ADA4250_RANGE_SET_MSK GENMASK(1, 0) 43 44/* Miscellaneous definitions */ 45#define ADA4250_CHIP_ID 0x4250 46#define ADA4250_RANGE1 0 47#define ADA4250_RANGE4 3 48 49/* ADA4250 current bias set */ 50enum ada4250_current_bias { 51 ADA4250_BIAS_DISABLED, 52 ADA4250_BIAS_BANDGAP, 53 ADA4250_BIAS_AVDD, 54}; 55 56struct ada4250_state { 57 struct spi_device *spi; 58 struct regmap *regmap; 59 struct regulator *reg; 60 /* Protect against concurrent accesses to the device and data content */ 61 struct mutex lock; 62 u8 bias; 63 u8 gain; 64 int offset_uv; 65 bool refbuf_en; 66}; 67 68/* ADA4250 Current Bias Source Settings: Disabled, Bandgap Reference, AVDD */ 69static const int calibbias_table[] = {0, 1, 2}; 70 71/* ADA4250 Gain (V/V) values: 1, 2, 4, 8, 16, 32, 64, 128 */ 72static const int hwgain_table[] = {1, 2, 4, 8, 16, 32, 64, 128}; 73 74static const struct regmap_config ada4250_regmap_config = { 75 .reg_bits = 8, 76 .val_bits = 8, 77 .read_flag_mask = BIT(7), 78 .max_register = 0x1A, 79}; 80 81static int ada4250_set_offset_uv(struct iio_dev *indio_dev, 82 const struct iio_chan_spec *chan, 83 int offset_uv) 84{ 85 struct ada4250_state *st = iio_priv(indio_dev); 86 87 int i, ret, x[8], max_vos, min_vos, voltage_v, vlsb = 0; 88 u8 offset_raw, range = ADA4250_RANGE1; 89 u32 lsb_coeff[6] = {1333, 2301, 4283, 8289, 16311, 31599}; 90 91 if (st->bias == 0 || st->bias == 3) 92 return -EINVAL; 93 94 voltage_v = regulator_get_voltage(st->reg); 95 voltage_v = DIV_ROUND_CLOSEST(voltage_v, 1000000); 96 97 if (st->bias == ADA4250_BIAS_AVDD) 98 x[0] = voltage_v; 99 else 100 x[0] = 5; 101 102 x[1] = 126 * (x[0] - 1); 103 104 for (i = 0; i < 6; i++) 105 x[i + 2] = DIV_ROUND_CLOSEST(x[1] * 1000, lsb_coeff[i]); 106 107 if (st->gain == 0) 108 return -EINVAL; 109 110 /* 111 * Compute Range and Voltage per LSB for the Sensor Offset Calibration 112 * Example of computation for Range 1 and Range 2 (Curren Bias Set = AVDD): 113 * Range 1 Range 2 114 * Gain | Max Vos(mV) | LSB(mV) | Max Vos(mV) | LSB(mV) | 115 * 2 | X1*127 | X1=0.126(AVDD-1) | X1*3*127 | X1*3 | 116 * 4 | X2*127 | X2=X1/1.3333 | X2*3*127 | X2*3 | 117 * 8 | X3*127 | X3=X1/2.301 | X3*3*127 | X3*3 | 118 * 16 | X4*127 | X4=X1/4.283 | X4*3*127 | X4*3 | 119 * 32 | X5*127 | X5=X1/8.289 | X5*3*127 | X5*3 | 120 * 64 | X6*127 | X6=X1/16.311 | X6*3*127 | X6*3 | 121 * 128 | X7*127 | X7=X1/31.599 | X7*3*127 | X7*3 | 122 */ 123 for (i = ADA4250_RANGE1; i <= ADA4250_RANGE4; i++) { 124 max_vos = x[st->gain] * 127 * ((1 << (i + 1)) - 1); 125 min_vos = -1 * max_vos; 126 if (offset_uv > min_vos && offset_uv < max_vos) { 127 range = i; 128 vlsb = x[st->gain] * ((1 << (i + 1)) - 1); 129 break; 130 } 131 } 132 133 if (vlsb <= 0) 134 return -EINVAL; 135 136 offset_raw = DIV_ROUND_CLOSEST(abs(offset_uv), vlsb); 137 138 mutex_lock(&st->lock); 139 ret = regmap_update_bits(st->regmap, ADA4250_REG_SNSR_CAL_CNFG, 140 ADA4250_RANGE_SET_MSK, 141 FIELD_PREP(ADA4250_RANGE_SET_MSK, range)); 142 if (ret) 143 goto exit; 144 145 st->offset_uv = offset_raw * vlsb; 146 147 /* 148 * To set the offset calibration value, use bits [6:0] and bit 7 as the 149 * polarity bit (set to "0" for a negative offset and "1" for a positive 150 * offset). 151 */ 152 if (offset_uv < 0) { 153 offset_raw |= BIT(7); 154 st->offset_uv *= (-1); 155 } 156 157 ret = regmap_write(st->regmap, ADA4250_REG_SNSR_CAL_VAL, offset_raw); 158 159exit: 160 mutex_unlock(&st->lock); 161 162 return ret; 163} 164 165static int ada4250_read_raw(struct iio_dev *indio_dev, 166 struct iio_chan_spec const *chan, 167 int *val, int *val2, long info) 168{ 169 struct ada4250_state *st = iio_priv(indio_dev); 170 int ret; 171 172 switch (info) { 173 case IIO_CHAN_INFO_HARDWAREGAIN: 174 ret = regmap_read(st->regmap, ADA4250_REG_GAIN_MUX, val); 175 if (ret) 176 return ret; 177 178 *val = BIT(*val); 179 180 return IIO_VAL_INT; 181 case IIO_CHAN_INFO_OFFSET: 182 *val = st->offset_uv; 183 184 return IIO_VAL_INT; 185 case IIO_CHAN_INFO_CALIBBIAS: 186 ret = regmap_read(st->regmap, ADA4250_REG_SNSR_CAL_CNFG, val); 187 if (ret) 188 return ret; 189 190 *val = FIELD_GET(ADA4250_BIAS_SET_MSK, *val); 191 192 return IIO_VAL_INT; 193 case IIO_CHAN_INFO_SCALE: 194 *val = 1; 195 *val2 = 1000000; 196 197 return IIO_VAL_FRACTIONAL; 198 default: 199 return -EINVAL; 200 } 201} 202 203static int ada4250_write_raw(struct iio_dev *indio_dev, 204 struct iio_chan_spec const *chan, 205 int val, int val2, long info) 206{ 207 struct ada4250_state *st = iio_priv(indio_dev); 208 int ret; 209 210 switch (info) { 211 case IIO_CHAN_INFO_HARDWAREGAIN: 212 ret = regmap_write(st->regmap, ADA4250_REG_GAIN_MUX, 213 FIELD_PREP(ADA4250_GAIN_MUX_MSK, ilog2(val))); 214 if (ret) 215 return ret; 216 217 st->gain = ilog2(val); 218 219 return ret; 220 case IIO_CHAN_INFO_OFFSET: 221 return ada4250_set_offset_uv(indio_dev, chan, val); 222 case IIO_CHAN_INFO_CALIBBIAS: 223 ret = regmap_update_bits(st->regmap, ADA4250_REG_SNSR_CAL_CNFG, 224 ADA4250_BIAS_SET_MSK, 225 FIELD_PREP(ADA4250_BIAS_SET_MSK, val)); 226 if (ret) 227 return ret; 228 229 st->bias = val; 230 231 return ret; 232 default: 233 return -EINVAL; 234 } 235} 236 237static int ada4250_read_avail(struct iio_dev *indio_dev, 238 struct iio_chan_spec const *chan, 239 const int **vals, int *type, int *length, 240 long mask) 241{ 242 switch (mask) { 243 case IIO_CHAN_INFO_CALIBBIAS: 244 *vals = calibbias_table; 245 *type = IIO_VAL_INT; 246 *length = ARRAY_SIZE(calibbias_table); 247 248 return IIO_AVAIL_LIST; 249 case IIO_CHAN_INFO_HARDWAREGAIN: 250 *vals = hwgain_table; 251 *type = IIO_VAL_INT; 252 *length = ARRAY_SIZE(hwgain_table); 253 254 return IIO_AVAIL_LIST; 255 default: 256 return -EINVAL; 257 } 258} 259 260static int ada4250_reg_access(struct iio_dev *indio_dev, 261 unsigned int reg, 262 unsigned int write_val, 263 unsigned int *read_val) 264{ 265 struct ada4250_state *st = iio_priv(indio_dev); 266 267 if (read_val) 268 return regmap_read(st->regmap, reg, read_val); 269 else 270 return regmap_write(st->regmap, reg, write_val); 271} 272 273static const struct iio_info ada4250_info = { 274 .read_raw = ada4250_read_raw, 275 .write_raw = ada4250_write_raw, 276 .read_avail = &ada4250_read_avail, 277 .debugfs_reg_access = &ada4250_reg_access, 278}; 279 280static const struct iio_chan_spec ada4250_channels[] = { 281 { 282 .type = IIO_VOLTAGE, 283 .output = 1, 284 .indexed = 1, 285 .channel = 0, 286 .info_mask_separate = BIT(IIO_CHAN_INFO_HARDWAREGAIN) | 287 BIT(IIO_CHAN_INFO_OFFSET) | 288 BIT(IIO_CHAN_INFO_CALIBBIAS) | 289 BIT(IIO_CHAN_INFO_SCALE), 290 .info_mask_separate_available = BIT(IIO_CHAN_INFO_CALIBBIAS) | 291 BIT(IIO_CHAN_INFO_HARDWAREGAIN), 292 } 293}; 294 295static void ada4250_reg_disable(void *data) 296{ 297 regulator_disable(data); 298} 299 300static int ada4250_init(struct ada4250_state *st) 301{ 302 int ret; 303 u16 chip_id; 304 u8 data[2] __aligned(8) = {}; 305 struct spi_device *spi = st->spi; 306 307 st->refbuf_en = device_property_read_bool(&spi->dev, "adi,refbuf-enable"); 308 309 st->reg = devm_regulator_get(&spi->dev, "avdd"); 310 if (IS_ERR(st->reg)) 311 return dev_err_probe(&spi->dev, PTR_ERR(st->reg), 312 "failed to get the AVDD voltage\n"); 313 314 ret = regulator_enable(st->reg); 315 if (ret) { 316 dev_err(&spi->dev, "Failed to enable specified AVDD supply\n"); 317 return ret; 318 } 319 320 ret = devm_add_action_or_reset(&spi->dev, ada4250_reg_disable, st->reg); 321 if (ret) 322 return ret; 323 324 ret = regmap_write(st->regmap, ADA4250_REG_RESET, 325 FIELD_PREP(ADA4250_RESET_MSK, 1)); 326 if (ret) 327 return ret; 328 329 ret = regmap_bulk_read(st->regmap, ADA4250_REG_CHIP_ID, data, 2); 330 if (ret) 331 return ret; 332 333 chip_id = get_unaligned_le16(data); 334 335 if (chip_id != ADA4250_CHIP_ID) { 336 dev_err(&spi->dev, "Invalid chip ID.\n"); 337 return -EINVAL; 338 } 339 340 return regmap_write(st->regmap, ADA4250_REG_REFBUF_EN, 341 FIELD_PREP(ADA4250_REFBUF_MSK, st->refbuf_en)); 342} 343 344static int ada4250_probe(struct spi_device *spi) 345{ 346 struct iio_dev *indio_dev; 347 struct regmap *regmap; 348 struct ada4250_state *st; 349 int ret; 350 351 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 352 if (!indio_dev) 353 return -ENOMEM; 354 355 regmap = devm_regmap_init_spi(spi, &ada4250_regmap_config); 356 if (IS_ERR(regmap)) 357 return PTR_ERR(regmap); 358 359 st = iio_priv(indio_dev); 360 st->regmap = regmap; 361 st->spi = spi; 362 363 indio_dev->info = &ada4250_info; 364 indio_dev->name = "ada4250"; 365 indio_dev->channels = ada4250_channels; 366 indio_dev->num_channels = ARRAY_SIZE(ada4250_channels); 367 368 mutex_init(&st->lock); 369 370 ret = ada4250_init(st); 371 if (ret) { 372 dev_err(&spi->dev, "ADA4250 init failed\n"); 373 return ret; 374 } 375 376 return devm_iio_device_register(&spi->dev, indio_dev); 377} 378 379static const struct spi_device_id ada4250_id[] = { 380 { "ada4250", 0 }, 381 {} 382}; 383MODULE_DEVICE_TABLE(spi, ada4250_id); 384 385static const struct of_device_id ada4250_of_match[] = { 386 { .compatible = "adi,ada4250" }, 387 {}, 388}; 389MODULE_DEVICE_TABLE(of, ada4250_of_match); 390 391static struct spi_driver ada4250_driver = { 392 .driver = { 393 .name = "ada4250", 394 .of_match_table = ada4250_of_match, 395 }, 396 .probe = ada4250_probe, 397 .id_table = ada4250_id, 398}; 399module_spi_driver(ada4250_driver); 400 401MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com"); 402MODULE_DESCRIPTION("Analog Devices ADA4250"); 403MODULE_LICENSE("GPL v2");