summaryrefslogtreecommitdiff
path: root/drivers/iio/adc/ad7266.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/adc/ad7266.c')
-rw-r--r--drivers/iio/adc/ad7266.c186
1 files changed, 61 insertions, 125 deletions
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
index c2744a75c3b0..3364ac6c4631 100644
--- a/drivers/iio/adc/ad7266.c
+++ b/drivers/iio/adc/ad7266.c
@@ -1,9 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* AD7266/65 SPI ADC driver
*
* Copyright 2012 Analog Devices Inc.
- *
- * Licensed under the GPL-2.
*/
#include <linux/device.h>
@@ -12,7 +11,7 @@
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/interrupt.h>
@@ -24,10 +23,11 @@
#include <linux/platform_data/ad7266.h>
+#define AD7266_INTERNAL_REF_MV 2500
+
struct ad7266_state {
struct spi_device *spi;
- struct regulator *reg;
- unsigned long vref_uv;
+ unsigned long vref_mv;
struct spi_transfer single_xfer[3];
struct spi_message single_msg;
@@ -35,43 +35,36 @@ struct ad7266_state {
enum ad7266_range range;
enum ad7266_mode mode;
bool fixed_addr;
- struct gpio gpios[3];
+ struct gpio_desc *gpios[3];
/*
- * DMA (thus cache coherency maintenance) requires the
+ * DMA (thus cache coherency maintenance) may require the
* transfer buffers to live in their own cache lines.
* The buffer needs to be large enough to hold two samples (4 bytes) and
* the naturally aligned timestamp (8 bytes).
*/
- uint8_t data[ALIGN(4, sizeof(s64)) + sizeof(s64)] ____cacheline_aligned;
+ struct {
+ __be16 sample[2];
+ aligned_s64 timestamp;
+ } data __aligned(IIO_DMA_MINALIGN);
};
static int ad7266_wakeup(struct ad7266_state *st)
{
/* Any read with >= 2 bytes will wake the device */
- return spi_read(st->spi, st->data, 2);
+ return spi_read(st->spi, &st->data.sample[0], 2);
}
static int ad7266_powerdown(struct ad7266_state *st)
{
/* Any read with < 2 bytes will powerdown the device */
- return spi_read(st->spi, st->data, 1);
+ return spi_read(st->spi, &st->data.sample[0], 1);
}
static int ad7266_preenable(struct iio_dev *indio_dev)
{
struct ad7266_state *st = iio_priv(indio_dev);
- int ret;
-
- ret = ad7266_wakeup(st);
- if (ret)
- return ret;
-
- ret = iio_sw_buffer_preenable(indio_dev);
- if (ret)
- ad7266_powerdown(st);
-
- return ret;
+ return ad7266_wakeup(st);
}
static int ad7266_postdisable(struct iio_dev *indio_dev)
@@ -82,8 +75,6 @@ static int ad7266_postdisable(struct iio_dev *indio_dev)
static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
.preenable = &ad7266_preenable,
- .postenable = &iio_triggered_buffer_postenable,
- .predisable = &iio_triggered_buffer_predisable,
.postdisable = &ad7266_postdisable,
};
@@ -94,12 +85,10 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p)
struct ad7266_state *st = iio_priv(indio_dev);
int ret;
- ret = spi_read(st->spi, st->data, 4);
- if (ret == 0) {
- if (indio_dev->scan_timestamp)
- ((s64 *)st->data)[1] = pf->timestamp;
- iio_push_to_buffers(indio_dev, (u8 *)st->data);
- }
+ ret = spi_read(st->spi, st->data.sample, 4);
+ if (ret == 0)
+ iio_push_to_buffers_with_ts(indio_dev, &st->data, sizeof(st->data),
+ pf->timestamp);
iio_trigger_notify_done(indio_dev->trig);
@@ -126,14 +115,15 @@ static void ad7266_select_input(struct ad7266_state *st, unsigned int nr)
}
for (i = 0; i < 3; ++i)
- gpio_set_value(st->gpios[i].gpio, (bool)(nr & BIT(i)));
+ gpiod_set_value(st->gpios[i], (bool)(nr & BIT(i)));
}
static int ad7266_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *scan_mask)
{
struct ad7266_state *st = iio_priv(indio_dev);
- unsigned int nr = find_first_bit(scan_mask, indio_dev->masklength);
+ unsigned int nr = find_first_bit(scan_mask,
+ iio_get_masklength(indio_dev));
ad7266_select_input(st, nr);
@@ -148,7 +138,7 @@ static int ad7266_read_single(struct ad7266_state *st, int *val,
ad7266_select_input(st, address);
ret = spi_sync(st->spi, &st->single_msg);
- *val = be16_to_cpu(st->data[address % 2]);
+ *val = be16_to_cpu(st->data.sample[address % 2]);
return ret;
}
@@ -157,34 +147,34 @@ static int ad7266_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val, int *val2, long m)
{
struct ad7266_state *st = iio_priv(indio_dev);
- unsigned long scale_uv;
+ unsigned long scale_mv;
int ret;
switch (m) {
case IIO_CHAN_INFO_RAW:
- if (iio_buffer_enabled(indio_dev))
+ if (!iio_device_claim_direct(indio_dev))
return -EBUSY;
-
ret = ad7266_read_single(st, val, chan->address);
- if (ret)
- return ret;
+ iio_device_release_direct(indio_dev);
+ if (ret < 0)
+ return ret;
*val = (*val >> 2) & 0xfff;
if (chan->scan_type.sign == 's')
- *val = sign_extend32(*val, 11);
+ *val = sign_extend32(*val,
+ chan->scan_type.realbits - 1);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
- scale_uv = (st->vref_uv * 100);
+ scale_mv = st->vref_mv;
if (st->mode == AD7266_MODE_DIFF)
- scale_uv *= 2;
+ scale_mv *= 2;
if (st->range == AD7266_RANGE_2VREF)
- scale_uv *= 2;
+ scale_mv *= 2;
- scale_uv >>= chan->scan_type.realbits;
- *val = scale_uv / 100000;
- *val2 = (scale_uv % 100000) * 10;
- return IIO_VAL_INT_PLUS_MICRO;
+ *val = scale_mv;
+ *val2 = chan->scan_type.realbits;
+ return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_OFFSET:
if (st->range == AD7266_RANGE_2VREF &&
st->mode != AD7266_MODE_DIFF)
@@ -290,10 +280,9 @@ static AD7266_DECLARE_DIFF_CHANNELS_FIXED(u, 'u');
static const struct iio_info ad7266_info = {
.read_raw = &ad7266_read_raw,
.update_scan_mode = &ad7266_update_scan_mode,
- .driver_module = THIS_MODULE,
};
-static unsigned long ad7266_available_scan_masks[] = {
+static const unsigned long ad7266_available_scan_masks[] = {
0x003,
0x00c,
0x030,
@@ -303,14 +292,14 @@ static unsigned long ad7266_available_scan_masks[] = {
0x000,
};
-static unsigned long ad7266_available_scan_masks_diff[] = {
+static const unsigned long ad7266_available_scan_masks_diff[] = {
0x003,
0x00c,
0x030,
0x000,
};
-static unsigned long ad7266_available_scan_masks_fixed[] = {
+static const unsigned long ad7266_available_scan_masks_fixed[] = {
0x003,
0x000,
};
@@ -318,7 +307,7 @@ static unsigned long ad7266_available_scan_masks_fixed[] = {
struct ad7266_chan_info {
const struct iio_chan_spec *channels;
unsigned int num_channels;
- unsigned long *scan_masks;
+ const unsigned long *scan_masks;
};
#define AD7266_CHAN_INFO_INDEX(_differential, _signed, _fixed) \
@@ -384,42 +373,31 @@ static void ad7266_init_channels(struct iio_dev *indio_dev)
indio_dev->channels = chan_info->channels;
indio_dev->num_channels = chan_info->num_channels;
indio_dev->available_scan_masks = chan_info->scan_masks;
- indio_dev->masklength = chan_info->num_channels - 1;
}
static const char * const ad7266_gpio_labels[] = {
- "AD0", "AD1", "AD2",
+ "ad0", "ad1", "ad2",
};
static int ad7266_probe(struct spi_device *spi)
{
- struct ad7266_platform_data *pdata = spi->dev.platform_data;
+ const struct ad7266_platform_data *pdata = dev_get_platdata(&spi->dev);
struct iio_dev *indio_dev;
struct ad7266_state *st;
unsigned int i;
int ret;
- indio_dev = iio_device_alloc(sizeof(*st));
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
st = iio_priv(indio_dev);
- st->reg = regulator_get(&spi->dev, "vref");
- if (!IS_ERR_OR_NULL(st->reg)) {
- ret = regulator_enable(st->reg);
- if (ret)
- goto error_put_reg;
-
- ret = regulator_get_voltage(st->reg);
- if (ret < 0)
- goto error_disable_reg;
+ ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref");
+ if (ret < 0 && ret != -ENODEV)
+ return ret;
- st->vref_uv = ret;
- } else {
- /* Use internal reference */
- st->vref_uv = 2500000;
- }
+ st->vref_mv = ret == -ENODEV ? AD7266_INTERNAL_REF_MV : ret / 1000;
if (pdata) {
st->fixed_addr = pdata->fixed_addr;
@@ -428,14 +406,14 @@ static int ad7266_probe(struct spi_device *spi)
if (!st->fixed_addr) {
for (i = 0; i < ARRAY_SIZE(st->gpios); ++i) {
- st->gpios[i].gpio = pdata->addr_gpios[i];
- st->gpios[i].flags = GPIOF_OUT_INIT_LOW;
- st->gpios[i].label = ad7266_gpio_labels[i];
+ st->gpios[i] = devm_gpiod_get(&spi->dev,
+ ad7266_gpio_labels[i],
+ GPIOD_OUT_LOW);
+ if (IS_ERR(st->gpios[i])) {
+ ret = PTR_ERR(st->gpios[i]);
+ return ret;
+ }
}
- ret = gpio_request_array(st->gpios,
- ARRAY_SIZE(st->gpios));
- if (ret)
- goto error_disable_reg;
}
} else {
st->fixed_addr = true;
@@ -443,10 +421,8 @@ static int ad7266_probe(struct spi_device *spi)
st->mode = AD7266_MODE_DIFF;
}
- spi_set_drvdata(spi, indio_dev);
st->spi = spi;
- indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &ad7266_info;
@@ -454,15 +430,15 @@ static int ad7266_probe(struct spi_device *spi)
ad7266_init_channels(indio_dev);
/* wakeup */
- st->single_xfer[0].rx_buf = &st->data;
+ st->single_xfer[0].rx_buf = &st->data.sample[0];
st->single_xfer[0].len = 2;
st->single_xfer[0].cs_change = 1;
/* conversion */
- st->single_xfer[1].rx_buf = &st->data;
+ st->single_xfer[1].rx_buf = st->data.sample;
st->single_xfer[1].len = 4;
st->single_xfer[1].cs_change = 1;
/* powerdown */
- st->single_xfer[2].tx_buf = &st->data;
+ st->single_xfer[2].tx_buf = &st->data.sample[0];
st->single_xfer[2].len = 1;
spi_message_init(&st->single_msg);
@@ -470,55 +446,17 @@ static int ad7266_probe(struct spi_device *spi)
spi_message_add_tail(&st->single_xfer[1], &st->single_msg);
spi_message_add_tail(&st->single_xfer[2], &st->single_msg);
- ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+ ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, &iio_pollfunc_store_time,
&ad7266_trigger_handler, &iio_triggered_buffer_setup_ops);
if (ret)
- goto error_free_gpios;
-
- ret = iio_device_register(indio_dev);
- if (ret)
- goto error_buffer_cleanup;
-
- return 0;
-
-error_buffer_cleanup:
- iio_triggered_buffer_cleanup(indio_dev);
-error_free_gpios:
- if (!st->fixed_addr)
- gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios));
-error_disable_reg:
- if (!IS_ERR_OR_NULL(st->reg))
- regulator_disable(st->reg);
-error_put_reg:
- if (!IS_ERR_OR_NULL(st->reg))
- regulator_put(st->reg);
-
- iio_device_free(indio_dev);
-
- return ret;
-}
-
-static int ad7266_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct ad7266_state *st = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
- iio_triggered_buffer_cleanup(indio_dev);
- if (!st->fixed_addr)
- gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios));
- if (!IS_ERR_OR_NULL(st->reg)) {
- regulator_disable(st->reg);
- regulator_put(st->reg);
- }
- iio_device_free(indio_dev);
+ return ret;
- return 0;
+ return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct spi_device_id ad7266_id[] = {
- {"ad7265", 0},
- {"ad7266", 0},
+ { "ad7265", 0 },
+ { "ad7266", 0 },
{ }
};
MODULE_DEVICE_TABLE(spi, ad7266_id);
@@ -526,10 +464,8 @@ MODULE_DEVICE_TABLE(spi, ad7266_id);
static struct spi_driver ad7266_driver = {
.driver = {
.name = "ad7266",
- .owner = THIS_MODULE,
},
.probe = ad7266_probe,
- .remove = ad7266_remove,
.id_table = ad7266_id,
};
module_spi_driver(ad7266_driver);