summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/iio/resolver/ad2s1210.c91
1 files changed, 88 insertions, 3 deletions
diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c
index 8fbde9517fe9..af063eb25e9c 100644
--- a/drivers/staging/iio/resolver/ad2s1210.c
+++ b/drivers/staging/iio/resolver/ad2s1210.c
@@ -76,7 +76,8 @@ struct ad2s1210_state {
struct regmap *regmap;
/** The external oscillator frequency in Hz. */
unsigned long clkin_hz;
- bool hysteresis;
+ /** Available raw hysteresis values based on resolution. */
+ int hysteresis_available[2];
u8 resolution;
/** For reading raw sample value via SPI. */
__be16 sample __aligned(IIO_DMA_MINALIGN);
@@ -311,6 +312,7 @@ static ssize_t ad2s1210_store_resolution(struct device *dev,
goto error_ret;
st->resolution = udata;
+ st->hysteresis_available[1] = 1 << (16 - st->resolution);
ret = len;
error_ret:
@@ -447,6 +449,35 @@ error_ret:
return ret;
}
+static int ad2s1210_get_hysteresis(struct ad2s1210_state *st, int *val)
+{
+ int ret;
+
+ mutex_lock(&st->lock);
+ ret = regmap_test_bits(st->regmap, AD2S1210_REG_CONTROL,
+ AD2S1210_ENABLE_HYSTERESIS);
+ mutex_unlock(&st->lock);
+
+ if (ret < 0)
+ return ret;
+
+ *val = ret << (16 - st->resolution);
+ return IIO_VAL_INT;
+}
+
+static int ad2s1210_set_hysteresis(struct ad2s1210_state *st, int val)
+{
+ int ret;
+
+ mutex_lock(&st->lock);
+ ret = regmap_update_bits(st->regmap, AD2S1210_REG_CONTROL,
+ AD2S1210_ENABLE_HYSTERESIS,
+ val ? AD2S1210_ENABLE_HYSTERESIS : 0);
+ mutex_unlock(&st->lock);
+
+ return ret;
+}
+
static const int ad2s1210_velocity_scale[] = {
17089132, /* 8.192MHz / (2*pi * 2500 / 2^15) */
42722830, /* 8.192MHz / (2*pi * 1000 / 2^15) */
@@ -479,7 +510,55 @@ static int ad2s1210_read_raw(struct iio_dev *indio_dev,
default:
return -EINVAL;
}
+ case IIO_CHAN_INFO_HYSTERESIS:
+ switch (chan->type) {
+ case IIO_ANGL:
+ return ad2s1210_get_hysteresis(st, val);
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad2s1210_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type,
+ int *length, long mask)
+{
+ struct ad2s1210_state *st = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_HYSTERESIS:
+ switch (chan->type) {
+ case IIO_ANGL:
+ *vals = st->hysteresis_available;
+ *type = IIO_VAL_INT;
+ *length = ARRAY_SIZE(st->hysteresis_available);
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+static int ad2s1210_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct ad2s1210_state *st = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_HYSTERESIS:
+ switch (chan->type) {
+ case IIO_ANGL:
+ return ad2s1210_set_hysteresis(st, val);
+ default:
+ return -EINVAL;
+ }
default:
return -EINVAL;
}
@@ -520,7 +599,10 @@ static const struct iio_chan_spec ad2s1210_channels[] = {
.indexed = 1,
.channel = 0,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_SCALE),
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_HYSTERESIS),
+ .info_mask_separate_available =
+ BIT(IIO_CHAN_INFO_HYSTERESIS),
}, {
.type = IIO_ANGL_VEL,
.indexed = 1,
@@ -596,6 +678,8 @@ static int ad2s1210_debugfs_reg_access(struct iio_dev *indio_dev,
static const struct iio_info ad2s1210_info = {
.read_raw = ad2s1210_read_raw,
+ .read_avail = ad2s1210_read_avail,
+ .write_raw = ad2s1210_write_raw,
.attrs = &ad2s1210_attribute_group,
.debugfs_reg_access = &ad2s1210_debugfs_reg_access,
};
@@ -711,8 +795,9 @@ static int ad2s1210_probe(struct spi_device *spi)
mutex_init(&st->lock);
st->sdev = spi;
- st->hysteresis = true;
st->resolution = 12;
+ st->hysteresis_available[0] = 0;
+ st->hysteresis_available[1] = 1 << (16 - st->resolution);
ret = ad2s1210_setup_clocks(st);
if (ret < 0)