Skip to content

Commit 5a06fbc

Browse files
committed
iio: adc: ad7768-1: add support for SPI offload
The AD7768-1 family supports sampling rates up to 1 MSPS, which exceeds the capabilities of conventional triggered buffer operations due to SPI transaction overhead and interrupt latency. Add SPI offload support to enable hardware-accelerated data acquisition that bypasses software SPI transactions using continuous data streaming. Signed-off-by: Jonathan Santos <Jonathan.Santos@analog.com> Reviewed-by: David Lechner <dlechner@baylibre.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
1 parent 864fa00 commit 5a06fbc

2 files changed

Lines changed: 185 additions & 3 deletions

File tree

drivers/iio/adc/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,8 +352,10 @@ config AD7768_1
352352
select REGMAP_SPI
353353
select RATIONAL
354354
select IIO_BUFFER
355+
select IIO_BUFFER_DMAENGINE
355356
select IIO_TRIGGER
356357
select IIO_TRIGGERED_BUFFER
358+
select SPI_OFFLOAD
357359
help
358360
Say yes here to build support for Analog Devices AD7768-1 SPI
359361
simultaneously sampling sigma-delta analog to digital converter (ADC).

drivers/iio/adc/ad7768-1.c

Lines changed: 183 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,15 @@
2525
#include <linux/regulator/consumer.h>
2626
#include <linux/regulator/driver.h>
2727
#include <linux/sysfs.h>
28+
#include <linux/spi/offload/consumer.h>
29+
#include <linux/spi/offload/provider.h>
2830
#include <linux/spi/spi.h>
2931
#include <linux/unaligned.h>
3032
#include <linux/units.h>
3133
#include <linux/util_macros.h>
3234

3335
#include <linux/iio/buffer.h>
36+
#include <linux/iio/buffer-dmaengine.h>
3437
#include <linux/iio/iio.h>
3538
#include <linux/iio/sysfs.h>
3639
#include <linux/iio/trigger.h>
@@ -161,6 +164,8 @@ enum ad7768_filter_regval {
161164
enum ad7768_scan_type {
162165
AD7768_SCAN_TYPE_NORMAL,
163166
AD7768_SCAN_TYPE_HIGH_SPEED,
167+
AD7768_SCAN_TYPE_OFFLOAD_NORMAL,
168+
AD7768_SCAN_TYPE_OFFLOAD_HIGH_SPEED,
164169
};
165170

166171
enum {
@@ -266,6 +271,18 @@ static const struct iio_scan_type ad7768_scan_type[] = {
266271
.storagebits = 16,
267272
.endianness = IIO_BE,
268273
},
274+
[AD7768_SCAN_TYPE_OFFLOAD_NORMAL] = {
275+
.sign = 's',
276+
.realbits = 24,
277+
.storagebits = 32,
278+
.endianness = IIO_CPU,
279+
},
280+
[AD7768_SCAN_TYPE_OFFLOAD_HIGH_SPEED] = {
281+
.sign = 's',
282+
.realbits = 16,
283+
.storagebits = 32,
284+
.endianness = IIO_CPU,
285+
},
269286
};
270287

271288
struct ad7768_chip_info {
@@ -283,6 +300,8 @@ struct ad7768_chip_info {
283300

284301
struct ad7768_state {
285302
struct spi_device *spi;
303+
struct spi_offload *offload;
304+
struct spi_offload_trigger *offload_trigger;
286305
struct regmap *regmap;
287306
struct regmap *regmap24;
288307
int vref_uv;
@@ -306,6 +325,8 @@ struct ad7768_state {
306325
struct gpio_desc *gpio_reset;
307326
const char *labels[AD7768_MAX_CHANNELS];
308327
struct gpio_chip gpiochip;
328+
struct spi_transfer offload_xfer;
329+
struct spi_message offload_msg;
309330
const struct ad7768_chip_info *chip;
310331
bool en_spi_sync;
311332
struct mutex pga_lock; /* protect device internal state (PGA) */
@@ -1117,6 +1138,10 @@ static int ad7768_get_current_scan_type(const struct iio_dev *indio_dev,
11171138
{
11181139
struct ad7768_state *st = iio_priv(indio_dev);
11191140

1141+
if (st->offload)
1142+
return st->oversampling_ratio == 8 ?
1143+
AD7768_SCAN_TYPE_OFFLOAD_HIGH_SPEED : AD7768_SCAN_TYPE_OFFLOAD_NORMAL;
1144+
11201145
return st->oversampling_ratio == 8 ?
11211146
AD7768_SCAN_TYPE_HIGH_SPEED : AD7768_SCAN_TYPE_NORMAL;
11221147
}
@@ -1339,6 +1364,78 @@ static const struct iio_buffer_setup_ops ad7768_buffer_ops = {
13391364
.predisable = &ad7768_buffer_predisable,
13401365
};
13411366

1367+
static int ad7768_offload_buffer_postenable(struct iio_dev *indio_dev)
1368+
{
1369+
struct ad7768_state *st = iio_priv(indio_dev);
1370+
struct spi_offload_trigger_config config = {
1371+
.type = SPI_OFFLOAD_TRIGGER_DATA_READY,
1372+
};
1373+
const struct iio_scan_type *scan_type;
1374+
unsigned int unused;
1375+
int ret;
1376+
1377+
scan_type = iio_get_current_scan_type(indio_dev, &indio_dev->channels[0]);
1378+
if (IS_ERR(scan_type))
1379+
return PTR_ERR(scan_type);
1380+
1381+
st->offload_xfer.len = spi_bpw_to_bytes(scan_type->realbits);
1382+
st->offload_xfer.bits_per_word = scan_type->realbits;
1383+
st->offload_xfer.offload_flags = SPI_OFFLOAD_XFER_RX_STREAM;
1384+
1385+
spi_message_init_with_transfers(&st->offload_msg, &st->offload_xfer, 1);
1386+
st->offload_msg.offload = st->offload;
1387+
1388+
ret = spi_optimize_message(st->spi, &st->offload_msg);
1389+
if (ret) {
1390+
dev_err(&st->spi->dev, "failed to prepare offload, err: %d\n", ret);
1391+
return ret;
1392+
}
1393+
1394+
/*
1395+
* Write a 1 to the LSB of the INTERFACE_FORMAT register to enter
1396+
* continuous read mode. Subsequent data reads do not require an
1397+
* initial 8-bit write to query the ADC_DATA register.
1398+
*/
1399+
ret = regmap_write(st->regmap, AD7768_REG_INTERFACE_FORMAT, 0x01);
1400+
if (ret)
1401+
goto err_unoptimize_message;
1402+
1403+
ret = spi_offload_trigger_enable(st->offload, st->offload_trigger,
1404+
&config);
1405+
if (ret)
1406+
goto err_exit_continuous_read_mode;
1407+
1408+
return 0;
1409+
1410+
err_exit_continuous_read_mode:
1411+
regmap_read(st->regmap24, AD7768_REG24_ADC_DATA, &unused);
1412+
1413+
err_unoptimize_message:
1414+
spi_unoptimize_message(&st->offload_msg);
1415+
1416+
return ret;
1417+
}
1418+
1419+
static int ad7768_offload_buffer_predisable(struct iio_dev *indio_dev)
1420+
{
1421+
struct ad7768_state *st = iio_priv(indio_dev);
1422+
unsigned int unused;
1423+
1424+
spi_offload_trigger_disable(st->offload, st->offload_trigger);
1425+
spi_unoptimize_message(&st->offload_msg);
1426+
1427+
/*
1428+
* To exit continuous read mode, perform a single read of the ADC_DATA
1429+
* reg (0x2C), which allows further configuration of the device.
1430+
*/
1431+
return regmap_read(st->regmap24, AD7768_REG24_ADC_DATA, &unused);
1432+
}
1433+
1434+
static const struct iio_buffer_setup_ops ad7768_offload_buffer_ops = {
1435+
.postenable = ad7768_offload_buffer_postenable,
1436+
.predisable = ad7768_offload_buffer_predisable,
1437+
};
1438+
13421439
static int ad7768_set_trigger_state(struct iio_trigger *trig, bool enable)
13431440
{
13441441
struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
@@ -1587,6 +1684,36 @@ static int ad7768_parse_aaf_gain(struct device *dev, struct ad7768_state *st)
15871684
return 0;
15881685
}
15891686

1687+
static bool ad7768_offload_trigger_match(struct spi_offload_trigger *trigger,
1688+
enum spi_offload_trigger_type type,
1689+
u64 *args, u32 nargs)
1690+
{
1691+
if (type != SPI_OFFLOAD_TRIGGER_DATA_READY)
1692+
return false;
1693+
1694+
/* Up to 2 args are allowed, but only 1 is used */
1695+
if (nargs == 0 || nargs > 2 || args[0] != AD7768_TRIGGER_SOURCE_DRDY)
1696+
return false;
1697+
1698+
return true;
1699+
}
1700+
1701+
static int ad7768_offload_trigger_request(struct spi_offload_trigger *trigger,
1702+
enum spi_offload_trigger_type type,
1703+
u64 *args, u32 nargs)
1704+
{
1705+
/* Should already be validated by match, but just in case */
1706+
if (nargs == 0 || nargs > 2)
1707+
return -EINVAL;
1708+
1709+
return 0;
1710+
}
1711+
1712+
static const struct spi_offload_trigger_ops ad7768_offload_trigger_ops = {
1713+
.match = ad7768_offload_trigger_match,
1714+
.request = ad7768_offload_trigger_request,
1715+
};
1716+
15901717
static const struct ad7768_chip_info ad7768_chip_info = {
15911718
.name = "ad7768-1",
15921719
.channel_spec = ad7768_channels,
@@ -1624,10 +1751,51 @@ static const struct ad7768_chip_info adaq7769_chip_info = {
16241751
.has_variable_aaf = true,
16251752
};
16261753

1754+
static const struct spi_offload_config ad7768_spi_offload_config = {
1755+
.capability_flags = SPI_OFFLOAD_CAP_TRIGGER | SPI_OFFLOAD_CAP_RX_STREAM_DMA,
1756+
};
1757+
1758+
static int ad7768_spi_offload_probe(struct iio_dev *indio_dev,
1759+
struct ad7768_state *st)
1760+
{
1761+
struct device *dev = &st->spi->dev;
1762+
struct spi_offload_trigger_info trigger_info = {
1763+
.fwnode = dev_fwnode(dev),
1764+
.ops = &ad7768_offload_trigger_ops,
1765+
.priv = st,
1766+
};
1767+
struct dma_chan *rx_dma;
1768+
int ret;
1769+
1770+
ret = devm_spi_offload_trigger_register(dev, &trigger_info);
1771+
if (ret)
1772+
return dev_err_probe(dev, ret, "failed to register offload trigger\n");
1773+
1774+
st->offload_trigger = devm_spi_offload_trigger_get(dev, st->offload,
1775+
SPI_OFFLOAD_TRIGGER_DATA_READY);
1776+
if (IS_ERR(st->offload_trigger))
1777+
return dev_err_probe(dev, PTR_ERR(st->offload_trigger),
1778+
"failed to get offload trigger\n");
1779+
1780+
rx_dma = devm_spi_offload_rx_stream_request_dma_chan(dev, st->offload);
1781+
if (IS_ERR(rx_dma))
1782+
return dev_err_probe(dev, PTR_ERR(rx_dma), "failed to get offload RX DMA\n");
1783+
1784+
ret = devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, rx_dma,
1785+
IIO_BUFFER_DIRECTION_IN);
1786+
if (ret)
1787+
return dev_err_probe(dev, ret, "failed to setup offload RX DMA\n");
1788+
1789+
indio_dev->setup_ops = &ad7768_offload_buffer_ops;
1790+
1791+
return 0;
1792+
}
1793+
16271794
static int ad7768_probe(struct spi_device *spi)
16281795
{
16291796
struct ad7768_state *st;
16301797
struct iio_dev *indio_dev;
1798+
struct device *dev = &spi->dev;
16311799
int ret;
16321800

16331801
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
@@ -1723,9 +1891,20 @@ static int ad7768_probe(struct spi_device *spi)
17231891
if (ret)
17241892
return ret;
17251893

1726-
ret = ad7768_triggered_buffer_alloc(indio_dev);
1727-
if (ret)
1728-
return ret;
1894+
st->offload = devm_spi_offload_get(dev, spi, &ad7768_spi_offload_config);
1895+
ret = PTR_ERR_OR_ZERO(st->offload);
1896+
if (ret == -ENODEV) {
1897+
/* If not using SPI offload, fall back to low speed usage */
1898+
ret = ad7768_triggered_buffer_alloc(indio_dev);
1899+
if (ret)
1900+
return ret;
1901+
} else if (ret) {
1902+
return dev_err_probe(dev, ret, "failed to get SPI offload\n");
1903+
} else {
1904+
ret = ad7768_spi_offload_probe(indio_dev, st);
1905+
if (ret)
1906+
return ret;
1907+
}
17291908

17301909
return devm_iio_device_register(&spi->dev, indio_dev);
17311910
}
@@ -1761,3 +1940,4 @@ module_spi_driver(ad7768_driver);
17611940
MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
17621941
MODULE_DESCRIPTION("Analog Devices AD7768-1 ADC driver");
17631942
MODULE_LICENSE("GPL v2");
1943+
MODULE_IMPORT_NS("IIO_DMAENGINE_BUFFER");

0 commit comments

Comments
 (0)