On Mon, 27 May 2019 15:56:47 +0300 Beniamin Bia <beniamin.bia@xxxxxxxxxx> wrote: > The device dependent options which are going to be different for devices > which will be supported in the future by this driver, > were moved in chip info for a more generic driver. This patch allows > supporting more devices by the driver. Also, it is an intermediate > step of adding support for ad7616 in software mode. > > Signed-off-by: Beniamin Bia <beniamin.bia@xxxxxxxxxx> > Acked-by: Jonathan Cameron <jic23@xxxxxxxxxx> Applied to the togreg branch of iio.git and pushed out as testing for the autobuilders to play with it. Thanks, Jonathan > --- > Changes in v2: > -nothing changed > > drivers/iio/adc/ad7606.c | 61 +++++++++++++++++++++++++++++----------- > drivers/iio/adc/ad7606.h | 15 +++++++++- > 2 files changed, 58 insertions(+), 18 deletions(-) > > diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c > index 24c70c3cefb4..c66ff22f32d2 100644 > --- a/drivers/iio/adc/ad7606.c > +++ b/drivers/iio/adc/ad7606.c > @@ -158,7 +158,7 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, > return IIO_VAL_INT; > case IIO_CHAN_INFO_SCALE: > *val = 0; > - *val2 = st->scale_avail[st->range]; > + *val2 = st->scale_avail[st->range[0]]; > return IIO_VAL_INT_PLUS_MICRO; > case IIO_CHAN_INFO_OVERSAMPLING_RATIO: > *val = st->oversampling; > @@ -194,6 +194,32 @@ static ssize_t in_voltage_scale_available_show(struct device *dev, > > static IIO_DEVICE_ATTR_RO(in_voltage_scale_available, 0); > > +static int ad7606_write_scale_hw(struct iio_dev *indio_dev, int ch, int val) > +{ > + struct ad7606_state *st = iio_priv(indio_dev); > + > + gpiod_set_value(st->gpio_range, val); > + > + return 0; > +} > + > +static int ad7606_write_os_hw(struct iio_dev *indio_dev, int val) > +{ > + struct ad7606_state *st = iio_priv(indio_dev); > + DECLARE_BITMAP(values, 3); > + > + values[0] = val; > + > + gpiod_set_array_value(ARRAY_SIZE(values), st->gpio_os->desc, > + st->gpio_os->info, values); > + > + /* AD7616 requires a reset to update value */ > + if (st->chip_info->os_req_reset) > + ad7606_reset(st); > + > + return 0; > +} > + > static int ad7606_write_raw(struct iio_dev *indio_dev, > struct iio_chan_spec const *chan, > int val, > @@ -201,15 +227,18 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, > long mask) > { > struct ad7606_state *st = iio_priv(indio_dev); > - DECLARE_BITMAP(values, 3); > - int i; > + int i, ret, ch = 0; > > switch (mask) { > case IIO_CHAN_INFO_SCALE: > mutex_lock(&st->lock); > i = find_closest(val2, st->scale_avail, st->num_scales); > - gpiod_set_value(st->gpio_range, i); > - st->range = i; > + ret = st->write_scale(indio_dev, chan->address, i); > + if (ret < 0) { > + mutex_unlock(&st->lock); > + return ret; > + } > + st->range[ch] = i; > mutex_unlock(&st->lock); > > return 0; > @@ -218,17 +247,12 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, > return -EINVAL; > i = find_closest(val, st->oversampling_avail, > st->num_os_ratios); > - > - values[0] = i; > - > mutex_lock(&st->lock); > - gpiod_set_array_value(ARRAY_SIZE(values), st->gpio_os->desc, > - st->gpio_os->info, values); > - > - /* AD7616 requires a reset to update value */ > - if (st->chip_info->os_req_reset) > - ad7606_reset(st); > - > + ret = st->write_os(indio_dev, i); > + if (ret < 0) { > + mutex_unlock(&st->lock); > + return ret; > + } > st->oversampling = st->oversampling_avail[i]; > mutex_unlock(&st->lock); > > @@ -536,7 +560,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, > st->bops = bops; > st->base_address = base_address; > /* tied to logic low, analog input range is +/- 5V */ > - st->range = 0; > + st->range[0] = 0; > st->oversampling = 1; > st->scale_avail = ad7606_scale_avail; > st->num_scales = ARRAY_SIZE(ad7606_scale_avail); > @@ -589,6 +613,9 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, > if (ret) > dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); > > + st->write_scale = ad7606_write_scale_hw; > + st->write_os = ad7606_write_os_hw; > + > st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", > indio_dev->name, indio_dev->id); > if (!st->trig) > @@ -643,7 +670,7 @@ static int ad7606_resume(struct device *dev) > struct ad7606_state *st = iio_priv(indio_dev); > > if (st->gpio_standby) { > - gpiod_set_value(st->gpio_range, st->range); > + gpiod_set_value(st->gpio_range, st->range[0]); > gpiod_set_value(st->gpio_standby, 1); > ad7606_reset(st); > } > diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h > index f9ef52131e74..143c30163df9 100644 > --- a/drivers/iio/adc/ad7606.h > +++ b/drivers/iio/adc/ad7606.h > @@ -16,6 +16,12 @@ > * oversampling ratios. > * @oversampling_num number of elements stored in oversampling_avail array > * @os_req_reset some devices require a reset to update oversampling > + * @write_scale_sw pointer to the function which writes the scale via spi > + in software mode > + * @write_os_sw pointer to the function which writes the os via spi > + in software mode > + * @sw_mode_config: pointer to a function which configured the device > + * for software mode > */ > struct ad7606_chip_info { > const struct iio_chan_spec *channels; > @@ -23,6 +29,9 @@ struct ad7606_chip_info { > const unsigned int *oversampling_avail; > unsigned int oversampling_num; > bool os_req_reset; > + int (*write_scale_sw)(struct iio_dev *indio_dev, int ch, int val); > + int (*write_os_sw)(struct iio_dev *indio_dev, int val); > + int (*sw_mode_config)(struct iio_dev *indio_dev); > }; > > /** > @@ -39,6 +48,8 @@ struct ad7606_chip_info { > * @oversampling_avail pointer to the array which stores the available > * oversampling ratios. > * @num_os_ratios number of elements stored in oversampling_avail array > + * @write_scale pointer to the function which writes the scale > + * @write_os pointer to the function which writes the os > * @lock protect sensor state from concurrent accesses to GPIOs > * @gpio_convst GPIO descriptor for conversion start signal (CONVST) > * @gpio_reset GPIO descriptor for device hard-reset > @@ -57,13 +68,15 @@ struct ad7606_state { > const struct ad7606_chip_info *chip_info; > struct regulator *reg; > const struct ad7606_bus_ops *bops; > - unsigned int range; > + unsigned int range[16]; > unsigned int oversampling; > void __iomem *base_address; > const unsigned int *scale_avail; > unsigned int num_scales; > const unsigned int *oversampling_avail; > unsigned int num_os_ratios; > + int (*write_scale)(struct iio_dev *indio_dev, int ch, int val); > + int (*write_os)(struct iio_dev *indio_dev, int val); > > struct mutex lock; /* protect sensor state */ > struct gpio_desc *gpio_convst;