| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5625, AD5625R, |
|---|
| 3 | 4 | * AD5627, AD5627R, AD5628, AD5629R, AD5645R, AD5647R, AD5648, AD5665, AD5665R, |
|---|
| .. | .. |
|---|
| 6 | 7 | * Digital to analog converters driver |
|---|
| 7 | 8 | * |
|---|
| 8 | 9 | * Copyright 2011 Analog Devices Inc. |
|---|
| 9 | | - * |
|---|
| 10 | | - * Licensed under the GPL-2. |
|---|
| 11 | 10 | */ |
|---|
| 12 | 11 | |
|---|
| 13 | 12 | #include <linux/device.h> |
|---|
| .. | .. |
|---|
| 69 | 68 | * struct ad5064_chip_info - chip specific information |
|---|
| 70 | 69 | * @shared_vref: whether the vref supply is shared between channels |
|---|
| 71 | 70 | * @internal_vref: internal reference voltage. 0 if the chip has no |
|---|
| 72 | | - internal vref. |
|---|
| 73 | | - * @channel: channel specification |
|---|
| 71 | + * internal vref. |
|---|
| 72 | + * @channels: channel specification |
|---|
| 74 | 73 | * @num_channels: number of channels |
|---|
| 75 | 74 | * @regmap_type: register map layout variant |
|---|
| 76 | 75 | */ |
|---|
| .. | .. |
|---|
| 99 | 98 | * @use_internal_vref: set to true if the internal reference voltage should be |
|---|
| 100 | 99 | * used. |
|---|
| 101 | 100 | * @write: register write callback |
|---|
| 101 | + * @lock: maintain consistency between cached and dev state |
|---|
| 102 | 102 | * @data: i2c/spi transfer buffers |
|---|
| 103 | 103 | */ |
|---|
| 104 | 104 | |
|---|
| .. | .. |
|---|
| 112 | 112 | bool use_internal_vref; |
|---|
| 113 | 113 | |
|---|
| 114 | 114 | ad5064_write_func write; |
|---|
| 115 | + struct mutex lock; |
|---|
| 115 | 116 | |
|---|
| 116 | 117 | /* |
|---|
| 117 | 118 | * DMA (thus cache coherency maintenance) requires the |
|---|
| .. | .. |
|---|
| 248 | 249 | struct ad5064_state *st = iio_priv(indio_dev); |
|---|
| 249 | 250 | int ret; |
|---|
| 250 | 251 | |
|---|
| 251 | | - mutex_lock(&indio_dev->mlock); |
|---|
| 252 | + mutex_lock(&st->lock); |
|---|
| 252 | 253 | st->pwr_down_mode[chan->channel] = mode + 1; |
|---|
| 253 | 254 | |
|---|
| 254 | 255 | ret = ad5064_sync_powerdown_mode(st, chan); |
|---|
| 255 | | - mutex_unlock(&indio_dev->mlock); |
|---|
| 256 | + mutex_unlock(&st->lock); |
|---|
| 256 | 257 | |
|---|
| 257 | 258 | return ret; |
|---|
| 258 | 259 | } |
|---|
| .. | .. |
|---|
| 291 | 292 | if (ret) |
|---|
| 292 | 293 | return ret; |
|---|
| 293 | 294 | |
|---|
| 294 | | - mutex_lock(&indio_dev->mlock); |
|---|
| 295 | + mutex_lock(&st->lock); |
|---|
| 295 | 296 | st->pwr_down[chan->channel] = pwr_down; |
|---|
| 296 | 297 | |
|---|
| 297 | 298 | ret = ad5064_sync_powerdown_mode(st, chan); |
|---|
| 298 | | - mutex_unlock(&indio_dev->mlock); |
|---|
| 299 | + mutex_unlock(&st->lock); |
|---|
| 299 | 300 | return ret ? ret : len; |
|---|
| 300 | 301 | } |
|---|
| 301 | 302 | |
|---|
| .. | .. |
|---|
| 349 | 350 | if (val >= (1 << chan->scan_type.realbits) || val < 0) |
|---|
| 350 | 351 | return -EINVAL; |
|---|
| 351 | 352 | |
|---|
| 352 | | - mutex_lock(&indio_dev->mlock); |
|---|
| 353 | + mutex_lock(&st->lock); |
|---|
| 353 | 354 | ret = ad5064_write(st, AD5064_CMD_WRITE_INPUT_N_UPDATE_N, |
|---|
| 354 | 355 | chan->address, val, chan->scan_type.shift); |
|---|
| 355 | 356 | if (ret == 0) |
|---|
| 356 | 357 | st->dac_cache[chan->channel] = val; |
|---|
| 357 | | - mutex_unlock(&indio_dev->mlock); |
|---|
| 358 | + mutex_unlock(&st->lock); |
|---|
| 358 | 359 | break; |
|---|
| 359 | 360 | default: |
|---|
| 360 | 361 | ret = -EINVAL; |
|---|
| .. | .. |
|---|
| 786 | 787 | "vrefD", |
|---|
| 787 | 788 | }; |
|---|
| 788 | 789 | |
|---|
| 789 | | -static const char * const ad5064_vref_name(struct ad5064_state *st, |
|---|
| 790 | +static const char *ad5064_vref_name(struct ad5064_state *st, |
|---|
| 790 | 791 | unsigned int vref) |
|---|
| 791 | 792 | { |
|---|
| 792 | 793 | return st->chip_info->shared_vref ? "vref" : ad5064_vref_names[vref]; |
|---|
| .. | .. |
|---|
| 856 | 857 | return -ENOMEM; |
|---|
| 857 | 858 | |
|---|
| 858 | 859 | st = iio_priv(indio_dev); |
|---|
| 860 | + mutex_init(&st->lock); |
|---|
| 859 | 861 | dev_set_drvdata(dev, indio_dev); |
|---|
| 860 | 862 | |
|---|
| 861 | 863 | st->chip_info = &ad5064_chip_info_tbl[type]; |
|---|
| .. | .. |
|---|
| 872 | 874 | return ret; |
|---|
| 873 | 875 | } |
|---|
| 874 | 876 | |
|---|
| 875 | | - indio_dev->dev.parent = dev; |
|---|
| 876 | 877 | indio_dev->name = name; |
|---|
| 877 | 878 | indio_dev->info = &ad5064_info; |
|---|
| 878 | 879 | indio_dev->modes = INDIO_DIRECT_MODE; |
|---|