mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 19:47:08 +02:00
iio: adc: ad7380: new driver for AD7380 ADCs
This adds a new driver for the AD7380 family ADCs. The driver currently implements basic support for the AD7380, AD7381, 2-channel differential ADCs. Support for additional single-ended, pseudo-differential and 4-channel chips that use the same register map as well as additional features of the chip will be added in future patches. [Julien Stephan: fix rx/tx buffer for regmap access] [Julien Stephan: fix scale issue] [Julien Stephan: use the new iio_device_claim_direct_scoped instead of iio_device_claim_direct_mode] Co-developed-by: Stefan Popa <stefan.popa@analog.com> Signed-off-by: Stefan Popa <stefan.popa@analog.com> Reviewed-by: Nuno Sa <nuno.sa@analog.com> Signed-off-by: David Lechner <dlechner@baylibre.com> [Julien Stephan: add datasheet links of supported parts] Signed-off-by: Julien Stephan <jstephan@baylibre.com> Link: https://lore.kernel.org/r/20240528-adding-new-ad738x-driver-v7-2-4cd70a4c12c8@baylibre.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
parent
c4ea781c20
commit
b095217c10
|
|
@ -447,6 +447,7 @@ S: Supported
|
||||||
W: https://wiki.analog.com/resources/tools-software/linux-drivers/iio-adc/ad738x
|
W: https://wiki.analog.com/resources/tools-software/linux-drivers/iio-adc/ad738x
|
||||||
W: https://ez.analog.com/linux-software-drivers
|
W: https://ez.analog.com/linux-software-drivers
|
||||||
F: Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml
|
F: Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml
|
||||||
|
F: drivers/iio/adc/ad7380.c
|
||||||
|
|
||||||
AD7877 TOUCHSCREEN DRIVER
|
AD7877 TOUCHSCREEN DRIVER
|
||||||
M: Michael Hennerich <michael.hennerich@analog.com>
|
M: Michael Hennerich <michael.hennerich@analog.com>
|
||||||
|
|
|
||||||
|
|
@ -160,6 +160,22 @@ config AD7298
|
||||||
To compile this driver as a module, choose M here: the
|
To compile this driver as a module, choose M here: the
|
||||||
module will be called ad7298.
|
module will be called ad7298.
|
||||||
|
|
||||||
|
config AD7380
|
||||||
|
tristate "Analog Devices AD7380 ADC driver"
|
||||||
|
depends on SPI_MASTER
|
||||||
|
select IIO_BUFFER
|
||||||
|
select IIO_TRIGGER
|
||||||
|
select IIO_TRIGGERED_BUFFER
|
||||||
|
help
|
||||||
|
AD7380 is a family of simultaneous sampling ADCs that share the same
|
||||||
|
SPI register map and have similar pinouts.
|
||||||
|
|
||||||
|
Say yes here to build support for Analog Devices AD7380 ADC and
|
||||||
|
similar chips.
|
||||||
|
|
||||||
|
To compile this driver as a module, choose M here: the module will be
|
||||||
|
called ad7380.
|
||||||
|
|
||||||
config AD7476
|
config AD7476
|
||||||
tristate "Analog Devices AD7476 1-channel ADCs driver and other similar devices from AD and TI"
|
tristate "Analog Devices AD7476 1-channel ADCs driver and other similar devices from AD and TI"
|
||||||
depends on SPI
|
depends on SPI
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ obj-$(CONFIG_AD7280) += ad7280a.o
|
||||||
obj-$(CONFIG_AD7291) += ad7291.o
|
obj-$(CONFIG_AD7291) += ad7291.o
|
||||||
obj-$(CONFIG_AD7292) += ad7292.o
|
obj-$(CONFIG_AD7292) += ad7292.o
|
||||||
obj-$(CONFIG_AD7298) += ad7298.o
|
obj-$(CONFIG_AD7298) += ad7298.o
|
||||||
|
obj-$(CONFIG_AD7380) += ad7380.o
|
||||||
obj-$(CONFIG_AD7476) += ad7476.o
|
obj-$(CONFIG_AD7476) += ad7476.o
|
||||||
obj-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o
|
obj-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o
|
||||||
obj-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o
|
obj-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o
|
||||||
|
|
|
||||||
438
drivers/iio/adc/ad7380.c
Normal file
438
drivers/iio/adc/ad7380.c
Normal file
|
|
@ -0,0 +1,438 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Analog Devices AD738x Simultaneous Sampling SAR ADCs
|
||||||
|
*
|
||||||
|
* Copyright 2017 Analog Devices Inc.
|
||||||
|
* Copyright 2024 BayLibre, SAS
|
||||||
|
*
|
||||||
|
* Datasheets of supported parts:
|
||||||
|
* ad7380/1 : https://www.analog.com/media/en/technical-documentation/data-sheets/AD7380-7381.pdf
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/bitfield.h>
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
#include <linux/cleanup.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/regulator/consumer.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/spi/spi.h>
|
||||||
|
|
||||||
|
#include <linux/iio/buffer.h>
|
||||||
|
#include <linux/iio/iio.h>
|
||||||
|
#include <linux/iio/trigger_consumer.h>
|
||||||
|
#include <linux/iio/triggered_buffer.h>
|
||||||
|
|
||||||
|
/* 2.5V internal reference voltage */
|
||||||
|
#define AD7380_INTERNAL_REF_MV 2500
|
||||||
|
|
||||||
|
/* reading and writing registers is more reliable at lower than max speed */
|
||||||
|
#define AD7380_REG_WR_SPEED_HZ 10000000
|
||||||
|
|
||||||
|
#define AD7380_REG_WR BIT(15)
|
||||||
|
#define AD7380_REG_REGADDR GENMASK(14, 12)
|
||||||
|
#define AD7380_REG_DATA GENMASK(11, 0)
|
||||||
|
|
||||||
|
#define AD7380_REG_ADDR_NOP 0x0
|
||||||
|
#define AD7380_REG_ADDR_CONFIG1 0x1
|
||||||
|
#define AD7380_REG_ADDR_CONFIG2 0x2
|
||||||
|
#define AD7380_REG_ADDR_ALERT 0x3
|
||||||
|
#define AD7380_REG_ADDR_ALERT_LOW_TH 0x4
|
||||||
|
#define AD7380_REG_ADDR_ALERT_HIGH_TH 0x5
|
||||||
|
|
||||||
|
#define AD7380_CONFIG1_OS_MODE BIT(9)
|
||||||
|
#define AD7380_CONFIG1_OSR GENMASK(8, 6)
|
||||||
|
#define AD7380_CONFIG1_CRC_W BIT(5)
|
||||||
|
#define AD7380_CONFIG1_CRC_R BIT(4)
|
||||||
|
#define AD7380_CONFIG1_ALERTEN BIT(3)
|
||||||
|
#define AD7380_CONFIG1_RES BIT(2)
|
||||||
|
#define AD7380_CONFIG1_REFSEL BIT(1)
|
||||||
|
#define AD7380_CONFIG1_PMODE BIT(0)
|
||||||
|
|
||||||
|
#define AD7380_CONFIG2_SDO2 GENMASK(9, 8)
|
||||||
|
#define AD7380_CONFIG2_SDO BIT(8)
|
||||||
|
#define AD7380_CONFIG2_RESET GENMASK(7, 0)
|
||||||
|
|
||||||
|
#define AD7380_CONFIG2_RESET_SOFT 0x3C
|
||||||
|
#define AD7380_CONFIG2_RESET_HARD 0xFF
|
||||||
|
|
||||||
|
#define AD7380_ALERT_LOW_TH GENMASK(11, 0)
|
||||||
|
#define AD7380_ALERT_HIGH_TH GENMASK(11, 0)
|
||||||
|
|
||||||
|
struct ad7380_chip_info {
|
||||||
|
const char *name;
|
||||||
|
const struct iio_chan_spec *channels;
|
||||||
|
unsigned int num_channels;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define AD7380_CHANNEL(index, bits) { \
|
||||||
|
.type = IIO_VOLTAGE, \
|
||||||
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
|
||||||
|
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
||||||
|
.indexed = 1, \
|
||||||
|
.differential = 1, \
|
||||||
|
.channel = 2 * (index), \
|
||||||
|
.channel2 = 2 * (index) + 1, \
|
||||||
|
.scan_index = (index), \
|
||||||
|
.scan_type = { \
|
||||||
|
.sign = 's', \
|
||||||
|
.realbits = (bits), \
|
||||||
|
.storagebits = 16, \
|
||||||
|
.endianness = IIO_CPU, \
|
||||||
|
}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFINE_AD7380_2_CHANNEL(name, bits) \
|
||||||
|
static const struct iio_chan_spec name[] = { \
|
||||||
|
AD7380_CHANNEL(0, bits), \
|
||||||
|
AD7380_CHANNEL(1, bits), \
|
||||||
|
IIO_CHAN_SOFT_TIMESTAMP(2), \
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_AD7380_2_CHANNEL(ad7380_channels, 16);
|
||||||
|
DEFINE_AD7380_2_CHANNEL(ad7381_channels, 14);
|
||||||
|
|
||||||
|
/* Since this is simultaneous sampling, we don't allow individual channels. */
|
||||||
|
static const unsigned long ad7380_2_channel_scan_masks[] = {
|
||||||
|
GENMASK(1, 0),
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct ad7380_chip_info ad7380_chip_info = {
|
||||||
|
.name = "ad7380",
|
||||||
|
.channels = ad7380_channels,
|
||||||
|
.num_channels = ARRAY_SIZE(ad7380_channels),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct ad7380_chip_info ad7381_chip_info = {
|
||||||
|
.name = "ad7381",
|
||||||
|
.channels = ad7381_channels,
|
||||||
|
.num_channels = ARRAY_SIZE(ad7381_channels),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ad7380_state {
|
||||||
|
const struct ad7380_chip_info *chip_info;
|
||||||
|
struct spi_device *spi;
|
||||||
|
struct regmap *regmap;
|
||||||
|
unsigned int vref_mv;
|
||||||
|
/*
|
||||||
|
* DMA (thus cache coherency maintenance) requires the
|
||||||
|
* transfer buffers to live in their own cache lines.
|
||||||
|
* Make the buffer large enough for 2 16-bit samples and one 64-bit
|
||||||
|
* aligned 64 bit timestamp.
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
u16 raw[2];
|
||||||
|
|
||||||
|
s64 ts __aligned(8);
|
||||||
|
} scan_data __aligned(IIO_DMA_MINALIGN);
|
||||||
|
u16 tx;
|
||||||
|
u16 rx;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ad7380_regmap_reg_write(void *context, unsigned int reg,
|
||||||
|
unsigned int val)
|
||||||
|
{
|
||||||
|
struct ad7380_state *st = context;
|
||||||
|
struct spi_transfer xfer = {
|
||||||
|
.speed_hz = AD7380_REG_WR_SPEED_HZ,
|
||||||
|
.bits_per_word = 16,
|
||||||
|
.len = 2,
|
||||||
|
.tx_buf = &st->tx,
|
||||||
|
};
|
||||||
|
|
||||||
|
st->tx = FIELD_PREP(AD7380_REG_WR, 1) |
|
||||||
|
FIELD_PREP(AD7380_REG_REGADDR, reg) |
|
||||||
|
FIELD_PREP(AD7380_REG_DATA, val);
|
||||||
|
|
||||||
|
return spi_sync_transfer(st->spi, &xfer, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ad7380_regmap_reg_read(void *context, unsigned int reg,
|
||||||
|
unsigned int *val)
|
||||||
|
{
|
||||||
|
struct ad7380_state *st = context;
|
||||||
|
struct spi_transfer xfers[] = {
|
||||||
|
{
|
||||||
|
.speed_hz = AD7380_REG_WR_SPEED_HZ,
|
||||||
|
.bits_per_word = 16,
|
||||||
|
.len = 2,
|
||||||
|
.tx_buf = &st->tx,
|
||||||
|
.cs_change = 1,
|
||||||
|
.cs_change_delay = {
|
||||||
|
.value = 10, /* t[CSH] */
|
||||||
|
.unit = SPI_DELAY_UNIT_NSECS,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
.speed_hz = AD7380_REG_WR_SPEED_HZ,
|
||||||
|
.bits_per_word = 16,
|
||||||
|
.len = 2,
|
||||||
|
.rx_buf = &st->rx,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
st->tx = FIELD_PREP(AD7380_REG_WR, 0) |
|
||||||
|
FIELD_PREP(AD7380_REG_REGADDR, reg) |
|
||||||
|
FIELD_PREP(AD7380_REG_DATA, 0);
|
||||||
|
|
||||||
|
ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
*val = FIELD_GET(AD7380_REG_DATA, st->rx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct regmap_config ad7380_regmap_config = {
|
||||||
|
.reg_bits = 3,
|
||||||
|
.val_bits = 12,
|
||||||
|
.reg_read = ad7380_regmap_reg_read,
|
||||||
|
.reg_write = ad7380_regmap_reg_write,
|
||||||
|
.max_register = AD7380_REG_ADDR_ALERT_HIGH_TH,
|
||||||
|
.can_sleep = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ad7380_debugfs_reg_access(struct iio_dev *indio_dev, u32 reg,
|
||||||
|
u32 writeval, u32 *readval)
|
||||||
|
{
|
||||||
|
iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
|
||||||
|
struct ad7380_state *st = iio_priv(indio_dev);
|
||||||
|
|
||||||
|
if (readval)
|
||||||
|
return regmap_read(st->regmap, reg, readval);
|
||||||
|
else
|
||||||
|
return regmap_write(st->regmap, reg, writeval);
|
||||||
|
}
|
||||||
|
unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t ad7380_trigger_handler(int irq, void *p)
|
||||||
|
{
|
||||||
|
struct iio_poll_func *pf = p;
|
||||||
|
struct iio_dev *indio_dev = pf->indio_dev;
|
||||||
|
struct ad7380_state *st = iio_priv(indio_dev);
|
||||||
|
struct spi_transfer xfer = {
|
||||||
|
.bits_per_word = st->chip_info->channels[0].scan_type.realbits,
|
||||||
|
.len = 4,
|
||||||
|
.rx_buf = st->scan_data.raw,
|
||||||
|
};
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = spi_sync_transfer(st->spi, &xfer, 1);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
iio_push_to_buffers_with_timestamp(indio_dev, &st->scan_data,
|
||||||
|
pf->timestamp);
|
||||||
|
|
||||||
|
out:
|
||||||
|
iio_trigger_notify_done(indio_dev->trig);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ad7380_read_direct(struct ad7380_state *st,
|
||||||
|
struct iio_chan_spec const *chan, int *val)
|
||||||
|
{
|
||||||
|
struct spi_transfer xfers[] = {
|
||||||
|
/* toggle CS (no data xfer) to trigger a conversion */
|
||||||
|
{
|
||||||
|
.speed_hz = AD7380_REG_WR_SPEED_HZ,
|
||||||
|
.bits_per_word = chan->scan_type.realbits,
|
||||||
|
.delay = {
|
||||||
|
.value = 190, /* t[CONVERT] */
|
||||||
|
.unit = SPI_DELAY_UNIT_NSECS,
|
||||||
|
},
|
||||||
|
.cs_change = 1,
|
||||||
|
.cs_change_delay = {
|
||||||
|
.value = 10, /* t[CSH] */
|
||||||
|
.unit = SPI_DELAY_UNIT_NSECS,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
/* then read both channels */
|
||||||
|
{
|
||||||
|
.speed_hz = AD7380_REG_WR_SPEED_HZ,
|
||||||
|
.bits_per_word = chan->scan_type.realbits,
|
||||||
|
.rx_buf = st->scan_data.raw,
|
||||||
|
.len = 4,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
*val = sign_extend32(st->scan_data.raw[chan->scan_index],
|
||||||
|
chan->scan_type.realbits - 1);
|
||||||
|
|
||||||
|
return IIO_VAL_INT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ad7380_read_raw(struct iio_dev *indio_dev,
|
||||||
|
struct iio_chan_spec const *chan,
|
||||||
|
int *val, int *val2, long info)
|
||||||
|
{
|
||||||
|
struct ad7380_state *st = iio_priv(indio_dev);
|
||||||
|
|
||||||
|
switch (info) {
|
||||||
|
case IIO_CHAN_INFO_RAW:
|
||||||
|
iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
|
||||||
|
return ad7380_read_direct(st, chan, val);
|
||||||
|
}
|
||||||
|
unreachable();
|
||||||
|
case IIO_CHAN_INFO_SCALE:
|
||||||
|
/*
|
||||||
|
* According to the datasheet, the LSB size for fully differential ADC is
|
||||||
|
* (2 × VREF) / 2^N, where N is the ADC resolution (i.e realbits)
|
||||||
|
*/
|
||||||
|
*val = st->vref_mv;
|
||||||
|
*val2 = chan->scan_type.realbits - 1;
|
||||||
|
|
||||||
|
return IIO_VAL_FRACTIONAL_LOG2;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct iio_info ad7380_info = {
|
||||||
|
.read_raw = &ad7380_read_raw,
|
||||||
|
.debugfs_reg_access = &ad7380_debugfs_reg_access,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ad7380_init(struct ad7380_state *st, struct regulator *vref)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* perform hard reset */
|
||||||
|
ret = regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2,
|
||||||
|
AD7380_CONFIG2_RESET,
|
||||||
|
FIELD_PREP(AD7380_CONFIG2_RESET,
|
||||||
|
AD7380_CONFIG2_RESET_HARD));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* select internal or external reference voltage */
|
||||||
|
ret = regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG1,
|
||||||
|
AD7380_CONFIG1_REFSEL,
|
||||||
|
FIELD_PREP(AD7380_CONFIG1_REFSEL,
|
||||||
|
vref ? 1 : 0));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* SPI 1-wire mode */
|
||||||
|
return regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2,
|
||||||
|
AD7380_CONFIG2_SDO,
|
||||||
|
FIELD_PREP(AD7380_CONFIG2_SDO, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ad7380_regulator_disable(void *p)
|
||||||
|
{
|
||||||
|
regulator_disable(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ad7380_probe(struct spi_device *spi)
|
||||||
|
{
|
||||||
|
struct iio_dev *indio_dev;
|
||||||
|
struct ad7380_state *st;
|
||||||
|
struct regulator *vref;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||||
|
if (!indio_dev)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
st = iio_priv(indio_dev);
|
||||||
|
st->spi = spi;
|
||||||
|
st->chip_info = spi_get_device_match_data(spi);
|
||||||
|
if (!st->chip_info)
|
||||||
|
return dev_err_probe(&spi->dev, -EINVAL, "missing match data\n");
|
||||||
|
|
||||||
|
vref = devm_regulator_get_optional(&spi->dev, "refio");
|
||||||
|
if (IS_ERR(vref)) {
|
||||||
|
if (PTR_ERR(vref) != -ENODEV)
|
||||||
|
return dev_err_probe(&spi->dev, PTR_ERR(vref),
|
||||||
|
"Failed to get refio regulator\n");
|
||||||
|
|
||||||
|
vref = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If there is no REFIO supply, then it means that we are using
|
||||||
|
* the internal 2.5V reference, otherwise REFIO is reference voltage.
|
||||||
|
*/
|
||||||
|
if (vref) {
|
||||||
|
ret = regulator_enable(vref);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = devm_add_action_or_reset(&spi->dev,
|
||||||
|
ad7380_regulator_disable, vref);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = regulator_get_voltage(vref);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
st->vref_mv = ret / 1000;
|
||||||
|
} else {
|
||||||
|
st->vref_mv = AD7380_INTERNAL_REF_MV;
|
||||||
|
}
|
||||||
|
|
||||||
|
st->regmap = devm_regmap_init(&spi->dev, NULL, st, &ad7380_regmap_config);
|
||||||
|
if (IS_ERR(st->regmap))
|
||||||
|
return dev_err_probe(&spi->dev, PTR_ERR(st->regmap),
|
||||||
|
"failed to allocate register map\n");
|
||||||
|
|
||||||
|
indio_dev->channels = st->chip_info->channels;
|
||||||
|
indio_dev->num_channels = st->chip_info->num_channels;
|
||||||
|
indio_dev->name = st->chip_info->name;
|
||||||
|
indio_dev->info = &ad7380_info;
|
||||||
|
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||||
|
indio_dev->available_scan_masks = ad7380_2_channel_scan_masks;
|
||||||
|
|
||||||
|
ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
|
||||||
|
iio_pollfunc_store_time,
|
||||||
|
ad7380_trigger_handler, NULL);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = ad7380_init(st, vref);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return devm_iio_device_register(&spi->dev, indio_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id ad7380_of_match_table[] = {
|
||||||
|
{ .compatible = "adi,ad7380", .data = &ad7380_chip_info },
|
||||||
|
{ .compatible = "adi,ad7381", .data = &ad7381_chip_info },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct spi_device_id ad7380_id_table[] = {
|
||||||
|
{ "ad7380", (kernel_ulong_t)&ad7380_chip_info },
|
||||||
|
{ "ad7381", (kernel_ulong_t)&ad7381_chip_info },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(spi, ad7380_id_table);
|
||||||
|
|
||||||
|
static struct spi_driver ad7380_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "ad7380",
|
||||||
|
.of_match_table = ad7380_of_match_table,
|
||||||
|
},
|
||||||
|
.probe = ad7380_probe,
|
||||||
|
.id_table = ad7380_id_table,
|
||||||
|
};
|
||||||
|
module_spi_driver(ad7380_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
|
||||||
|
MODULE_DESCRIPTION("Analog Devices AD738x ADC driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
Loading…
Reference in New Issue
Block a user