Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

iio: dac: ds4424: add Rfs-based scale and per-variant limits

Parse optional maxim,rfs-ohms values to derive the per-channel output
current scale (mA per step) for the IIO current ABI.

Behavior changes:
- If maxim,rfs-ohms is present, IIO_CHAN_INFO_SCALE becomes available
and reports mA/step derived from Rfs.
- If maxim,rfs-ohms is missing, SCALE is not exposed to keep older DTs
working without requiring updates.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Oleksij Rempel and committed by
Jonathan Cameron
af980a79 f789b8cc

+80 -1
+80 -1
drivers/iio/dac/ds4424.c
··· 12 12 #include <linux/i2c.h> 13 13 #include <linux/kernel.h> 14 14 #include <linux/module.h> 15 + #include <linux/property.h> 15 16 #include <linux/regmap.h> 16 17 #include <linux/regulator/consumer.h> 17 18 #include <linux/time64.h> ··· 39 38 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 40 39 } 41 40 41 + #define DS4424_CHANNEL_WITH_SCALE(chan) { \ 42 + .type = IIO_CURRENT, \ 43 + .indexed = 1, \ 44 + .output = 1, \ 45 + .channel = chan, \ 46 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 47 + BIT(IIO_CHAN_INFO_SCALE), \ 48 + } 49 + 42 50 struct ds4424_chip_info { 43 51 const char *name; 52 + int vref_mV; 53 + int scale_denom; 44 54 u8 result_mask; 45 55 u8 num_channels; 46 56 }; 47 57 48 58 static const struct ds4424_chip_info ds4402_info = { 49 59 .name = "ds4402", 60 + .vref_mV = 1230, 61 + .scale_denom = 4, 50 62 .result_mask = DS4404_DAC_MASK, 51 63 .num_channels = DS4422_MAX_DAC_CHANNELS, 52 64 }; 53 65 54 66 static const struct ds4424_chip_info ds4404_info = { 55 67 .name = "ds4404", 68 + .vref_mV = 1230, 69 + .scale_denom = 4, 56 70 .result_mask = DS4404_DAC_MASK, 57 71 .num_channels = DS4424_MAX_DAC_CHANNELS, 58 72 }; 59 73 60 74 static const struct ds4424_chip_info ds4422_info = { 61 75 .name = "ds4422", 76 + .vref_mV = 976, 77 + .scale_denom = 16, 62 78 .result_mask = DS4424_DAC_MASK, 63 79 .num_channels = DS4422_MAX_DAC_CHANNELS, 64 80 }; 65 81 66 82 static const struct ds4424_chip_info ds4424_info = { 67 83 .name = "ds4424", 84 + .vref_mV = 976, 85 + .scale_denom = 16, 68 86 .result_mask = DS4424_DAC_MASK, 69 87 .num_channels = DS4424_MAX_DAC_CHANNELS, 70 88 }; ··· 92 72 struct regmap *regmap; 93 73 struct regulator *vcc_reg; 94 74 const struct ds4424_chip_info *chip_info; 75 + u32 rfs_ohms[DS4424_MAX_DAC_CHANNELS]; 76 + bool has_rfs; 95 77 }; 96 78 97 79 static const struct iio_chan_spec ds4424_channels[] = { ··· 101 79 DS4424_CHANNEL(1), 102 80 DS4424_CHANNEL(2), 103 81 DS4424_CHANNEL(3), 82 + }; 83 + 84 + static const struct iio_chan_spec ds4424_channels_with_scale[] = { 85 + DS4424_CHANNEL_WITH_SCALE(0), 86 + DS4424_CHANNEL_WITH_SCALE(1), 87 + DS4424_CHANNEL_WITH_SCALE(2), 88 + DS4424_CHANNEL_WITH_SCALE(3), 104 89 }; 105 90 106 91 static const struct regmap_range ds44x2_ranges[] = { ··· 202 173 *val = -*val; 203 174 204 175 return IIO_VAL_INT; 176 + case IIO_CHAN_INFO_SCALE: 177 + if (!data->has_rfs) 178 + return -EINVAL; 179 + 180 + /* SCALE is mA/step: mV / Ohm = mA. */ 181 + *val = data->chip_info->vref_mV; 182 + *val2 = data->rfs_ohms[chan->channel] * 183 + data->chip_info->scale_denom; 184 + return IIO_VAL_FRACTIONAL; 205 185 206 186 default: 207 187 return -EINVAL; ··· 247 209 default: 248 210 return -EINVAL; 249 211 } 212 + } 213 + 214 + static int ds4424_parse_rfs(struct i2c_client *client, 215 + struct ds4424_data *data, 216 + struct iio_dev *indio_dev) 217 + { 218 + struct device *dev = &client->dev; 219 + int count, ret; 220 + 221 + if (!device_property_present(dev, "maxim,rfs-ohms")) 222 + return 0; 223 + 224 + count = device_property_count_u32(dev, "maxim,rfs-ohms"); 225 + if (count < 0) 226 + return dev_err_probe(dev, count, "Failed to count maxim,rfs-ohms entries\n"); 227 + if (count != indio_dev->num_channels) 228 + return dev_err_probe(dev, -EINVAL, "maxim,rfs-ohms must have %u entries\n", 229 + indio_dev->num_channels); 230 + 231 + ret = device_property_read_u32_array(dev, "maxim,rfs-ohms", 232 + data->rfs_ohms, 233 + indio_dev->num_channels); 234 + if (ret) 235 + return dev_err_probe(dev, ret, "Failed to read maxim,rfs-ohms property\n"); 236 + 237 + for (unsigned int i = 0; i < indio_dev->num_channels; i++) { 238 + if (!data->rfs_ohms[i]) 239 + return dev_err_probe(dev, -EINVAL, "maxim,rfs-ohms entry %u is zero\n", i); 240 + } 241 + 242 + data->has_rfs = true; 243 + 244 + return 0; 250 245 } 251 246 252 247 static int ds4424_suspend(struct device *dev) ··· 361 290 fsleep(1 * USEC_PER_MSEC); 362 291 363 292 indio_dev->num_channels = chip_info->num_channels; 364 - indio_dev->channels = ds4424_channels; 365 293 indio_dev->modes = INDIO_DIRECT_MODE; 366 294 indio_dev->info = &ds4424_iio_info; 367 295 368 296 ret = ds4424_init_regmap(client, indio_dev); 369 297 if (ret) 370 298 goto fail; 299 + 300 + ret = ds4424_parse_rfs(client, data, indio_dev); 301 + if (ret) 302 + goto fail; 303 + 304 + if (data->has_rfs) 305 + indio_dev->channels = ds4424_channels_with_scale; 306 + else 307 + indio_dev->channels = ds4424_channels; 371 308 372 309 ret = iio_device_register(indio_dev); 373 310 if (ret < 0) {