The AD5110/AD5112/AD5114 provide a nonvolatile solution
for 128-/64-/32-position adjustment applications, offering
guaranteed low resistor tolerance errors of ±8% and up to
±6 mA current density.
Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/AD5110_5112_5114.pdf
Signed-off-by: Mugilraj Dhavachelvan <dmugil2000@xxxxxxxxx>
[...]
+static int ad5110_write(struct ad5110_data *data, u8 cmd, u8 val)
+{
+ int ret;
+
+ mutex_lock(&data->lock);
+ data->buf[0] = cmd;
+ data->buf[1] = val;
+
+ ret = i2c_master_send_dmasafe(data->client, data->buf, sizeof(data->buf));
+ mutex_unlock(&data->lock);
+
+ return ret < 0 ? ret : 0;
+}
+
+static int ad5110_resistor_tol(struct ad5110_data *data, u8 cmd, int val)
+{
+ int ret;
+
+ ret = ad5110_read(data, cmd, &val);
+ if (ret)
+ return ret;
+
+ data->tol = FIELD_GET(GENMASK(6, 3), val);
+ data->tol = ((val & GENMASK(2, 0)) * 1000 / 8) + data->tol * 1000;
+ data->tol = data->cfg->kohms * data->tol / 100;
+ if (!(val & BIT(7)))Maybe apply shift to get consistent behavior with `raw`.
+ data->tol *= -1;
+
+ return 0;
+}
+
+static ssize_t ad5110_eeprom_read(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct ad5110_data *data = iio_priv(indio_dev);
+ int val = AD5110_WIPER_POS;
+ int ret;
+
+ ret = ad5110_read(data, AD5110_EEPROM_RD, &val);
+ if (ret)
+ return ret;
+This is new custom ABI and needs to be documented.
+ return iio_format_value(buf, IIO_VAL_INT, 1, &val);
+}
+
+static ssize_t ad5110_eeprom_write(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct ad5110_data *data = iio_priv(indio_dev);
+ int ret;
+
+ ret = ad5110_write(data, AD5110_EEPROM_WR, 0);
+ if (ret) {
+ dev_err(&data->client->dev, "RDAC to EEPROM write failed\n");
+ return ret;
+ }
+ msleep(20);
+
+ return len;
+}
+
+static IIO_DEVICE_ATTR(wiper_pos_eeprom, 0644,
+ ad5110_eeprom_read,
+ ad5110_eeprom_write, 0);
+static int ad5110_write_raw(struct iio_dev *indio_dev,val == data->cfg->max_pos is a valid setting. Writing max_pos puts it in top-scale mode which gives maximum resistance.
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct ad5110_data *data = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ if (val >= data->cfg->max_pos || val < 0)
+ return -EINVAL;Doesn't val have to be inverted to get the right behavior?
+
+ return ad5110_write(data, AD5110_RDAC_WR, val << data->cfg->shift);
+ case IIO_CHAN_INFO_ENABLE:
+ if (val < 0 || val > 1)
+ return -EINVAL;
+ if (data->enable == val)
+ return 0;
+ ret = ad5110_write(data, AD5110_SHUTDOWN, val);
+ if (ret)[...]
+ return ret;
+ data->enable = val;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}