Skip to content

Commit 49d7414

Browse files
dlechmachschmitt
authored andcommitted
iio: adc: ad7380: add support for multiple SPI lanes
Add support for multiple SPI lanes to increase throughput. The AD7380 family of ADCs have multiple SDO lines on the chip that can be used to read each channel on a separate SPI lane. If wired up to a SPI controller that supports it, the driver will now take advantage of this feature. This allows reaching the maximum sample rate advertised in the datasheet when combined with SPI offloading. [marcelo.schmitt@analog.com: drop SDO_X_WIRE, making similar to upstream] Reviewed-by: Nuno Sá <nuno.sa@analog.com> Reviewed-by: Marcelo Schmitt <marcelo.schmitt@analog.com> Signed-off-by: David Lechner <dlechner@baylibre.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
1 parent 834874e commit 49d7414

File tree

1 file changed

+41
-64
lines changed

1 file changed

+41
-64
lines changed

drivers/iio/adc/ad7380.c

Lines changed: 41 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,7 @@
7777
#define AD7380_CONFIG1_REFSEL BIT(1)
7878
#define AD7380_CONFIG1_PMODE BIT(0)
7979

80-
#define AD7380_CONFIG2_SDO2 GENMASK(9, 8)
81-
#define AD7380_CONFIG2_SDO BIT(8)
82-
#define AD7380_CONFIG2_SDO_2_WIRE 0
83-
#define AD7380_CONFIG2_SDO_1_WIRE 1
84-
#define AD7380_CONFIG2_SDO_4_WIRE 2
80+
#define AD7380_CONFIG2_SDO GENMASK(9, 8)
8581
#define AD7380_CONFIG2_RESET GENMASK(7, 0)
8682

8783
#define AD7380_CONFIG2_RESET_SOFT 0x3C
@@ -95,11 +91,6 @@
9591
#define T_CONVERT_X_NS 500 /* xth conversion start time (oversampling) */
9692
#define T_POWERUP_US 5000 /* Power up */
9793

98-
/*
99-
* AD738x support several SDO lines to increase throughput, but driver currently
100-
* supports only 1 SDO line (standard SPI transaction)
101-
*/
102-
#define AD7380_NUM_SDO_LINES 1
10394
#define AD7380_DEFAULT_GAIN_MILLI 1000
10495

10596
/*
@@ -891,6 +882,8 @@ struct ad7380_state {
891882
bool resolution_boost_enabled;
892883
unsigned int ch;
893884
bool seq;
885+
/* How many SDO lines are wired up. */
886+
u8 num_sdo_lines;
894887
unsigned int vref_mv;
895888
unsigned int vcm_mv[MAX_NUM_CHANNELS];
896889
unsigned int gain_milli[MAX_NUM_CHANNELS];
@@ -904,7 +897,6 @@ struct ad7380_state {
904897
struct spi_offload *offload;
905898
struct spi_offload_trigger *offload_trigger;
906899
unsigned long offload_trigger_hz;
907-
u32 num_sdi;
908900

909901
int sample_freq_range[3];
910902
/*
@@ -1090,7 +1082,7 @@ static int ad7380_set_ch(struct ad7380_state *st, unsigned int ch)
10901082
if (oversampling_ratio > 1)
10911083
xfer.delay.value = T_CONVERT_0_NS +
10921084
T_CONVERT_X_NS * (oversampling_ratio - 1) *
1093-
st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES;
1085+
st->chip_info->num_simult_channels / st->num_sdo_lines;
10941086

10951087
return spi_sync_transfer(st->spi, &xfer, 1);
10961088
}
@@ -1119,7 +1111,7 @@ static int ad7380_update_xfers(struct ad7380_state *st,
11191111
if (oversampling_ratio > 1)
11201112
t_convert = T_CONVERT_0_NS + T_CONVERT_X_NS *
11211113
(oversampling_ratio - 1) *
1122-
st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES;
1114+
st->chip_info->num_simult_channels / st->num_sdo_lines;
11231115

11241116
if (st->seq) {
11251117
xfer[0].delay.value = xfer[1].delay.value = t_convert;
@@ -1203,8 +1195,9 @@ static int ad7380_init_offload_msg(struct ad7380_state *st,
12031195

12041196
xfer->bits_per_word = scan_type->realbits;
12051197
xfer->offload_flags = SPI_OFFLOAD_XFER_RX_STREAM;
1206-
xfer->len = AD7380_SPI_BYTES(scan_type) *
1207-
st->chip_info->num_simult_channels / st->num_sdi;
1198+
xfer->len = AD7380_SPI_BYTES(scan_type) * st->chip_info->num_simult_channels;
1199+
if (st->num_sdo_lines > 1)
1200+
xfer->multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE;
12081201

12091202
spi_message_init_with_transfers(&st->offload_msg, xfer, 1);
12101203
st->offload_msg.offload = st->offload;
@@ -1228,7 +1221,6 @@ static int ad7380_offload_buffer_postenable(struct iio_dev *indio_dev)
12281221
.frequency_hz = st->offload_trigger_hz,
12291222
},
12301223
};
1231-
u32 sdo;
12321224
int ret;
12331225

12341226
ret = ad7380_init_offload_msg(st, indio_dev);
@@ -1243,38 +1235,9 @@ static int ad7380_offload_buffer_postenable(struct iio_dev *indio_dev)
12431235
if (st->seq)
12441236
config.periodic.frequency_hz *= 2;
12451237

1246-
switch (st->num_sdi) {
1247-
case 2:
1248-
sdo = AD7380_CONFIG2_SDO_2_WIRE;
1249-
break;
1250-
case 4:
1251-
sdo = AD7380_CONFIG2_SDO_4_WIRE;
1252-
break;
1253-
default:
1254-
sdo = AD7380_CONFIG2_SDO_1_WIRE;
1255-
break;
1256-
}
1257-
1258-
ret = regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2,
1259-
AD7380_CONFIG2_SDO2,
1260-
FIELD_PREP(AD7380_CONFIG2_SDO2, sdo));
1261-
if (ret)
1262-
goto err_unoptimize;
1263-
12641238
ret = spi_offload_trigger_enable(st->offload, st->offload_trigger, &config);
12651239
if (ret)
1266-
goto err_restore_sdo;
1267-
1268-
return 0;
1269-
1270-
err_restore_sdo:
1271-
regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2,
1272-
AD7380_CONFIG2_SDO2,
1273-
FIELD_PREP(AD7380_CONFIG2_SDO2,
1274-
AD7380_CONFIG2_SDO_1_WIRE));
1275-
1276-
err_unoptimize:
1277-
spi_unoptimize_message(&st->offload_msg);
1240+
spi_unoptimize_message(&st->offload_msg);
12781241

12791242
return ret;
12801243
}
@@ -1287,11 +1250,6 @@ static int ad7380_offload_buffer_predisable(struct iio_dev *indio_dev)
12871250
spi_offload_trigger_disable(st->offload, st->offload_trigger);
12881251
spi_unoptimize_message(&st->offload_msg);
12891252

1290-
regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2,
1291-
AD7380_CONFIG2_SDO2,
1292-
FIELD_PREP(AD7380_CONFIG2_SDO2,
1293-
AD7380_CONFIG2_SDO_1_WIRE));
1294-
12951253
if (st->seq) {
12961254
ret = regmap_update_bits(st->regmap,
12971255
AD7380_REG_ADDR_CONFIG1,
@@ -1842,6 +1800,7 @@ static const struct iio_info ad7380_info = {
18421800

18431801
static int ad7380_init(struct ad7380_state *st, bool external_ref_en)
18441802
{
1803+
u32 sdo;
18451804
int ret;
18461805

18471806
/* perform hard reset */
@@ -1864,11 +1823,24 @@ static int ad7380_init(struct ad7380_state *st, bool external_ref_en)
18641823
st->ch = 0;
18651824
st->seq = false;
18661825

1867-
/* SPI 1-wire mode */
1826+
/* SDO field has an irregular mapping. */
1827+
switch (st->num_sdo_lines) {
1828+
case 1:
1829+
sdo = 1;
1830+
break;
1831+
case 2:
1832+
sdo = 0;
1833+
break;
1834+
case 4:
1835+
sdo = 2;
1836+
break;
1837+
default:
1838+
return -EINVAL;
1839+
}
1840+
18681841
return regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2,
1869-
AD7380_CONFIG2_SDO2,
1870-
FIELD_PREP(AD7380_CONFIG2_SDO2,
1871-
AD7380_CONFIG2_SDO_1_WIRE));
1842+
AD7380_CONFIG2_SDO,
1843+
FIELD_PREP(AD7380_CONFIG2_SDO, sdo));
18721844
}
18731845

18741846
static int ad7380_probe_spi_offload(struct iio_dev *indio_dev,
@@ -1891,7 +1863,7 @@ static int ad7380_probe_spi_offload(struct iio_dev *indio_dev,
18911863
"failed to get offload trigger\n");
18921864

18931865
sample_rate = st->chip_info->max_conversion_rate_hz *
1894-
AD7380_NUM_SDO_LINES / st->chip_info->num_simult_channels;
1866+
st->num_sdo_lines / st->chip_info->num_simult_channels;
18951867

18961868
st->sample_freq_range[0] = 1; /* min */
18971869
st->sample_freq_range[1] = 1; /* step */
@@ -1936,6 +1908,13 @@ static int ad7380_probe(struct spi_device *spi)
19361908
if (!st->chip_info)
19371909
return dev_err_probe(dev, -EINVAL, "missing match data\n");
19381910

1911+
st->num_sdo_lines = spi->num_rx_lanes;
1912+
1913+
if (st->num_sdo_lines < 1 || st->num_sdo_lines > st->chip_info->num_simult_channels)
1914+
return dev_err_probe(dev, -EINVAL,
1915+
"invalid number of SDO lines (%d)\n",
1916+
st->num_sdo_lines);
1917+
19391918
ret = devm_regulator_bulk_get_enable(dev, st->chip_info->num_supplies,
19401919
st->chip_info->supplies);
19411920

@@ -2059,6 +2038,8 @@ static int ad7380_probe(struct spi_device *spi)
20592038
st->normal_xfer[0].cs_change_delay.value = st->chip_info->timing_specs->t_csh_ns;
20602039
st->normal_xfer[0].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
20612040
st->normal_xfer[1].rx_buf = st->scan_data;
2041+
if (st->num_sdo_lines > 1)
2042+
st->normal_xfer[1].multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE;
20622043

20632044
spi_message_init_with_transfers(&st->normal_msg, st->normal_xfer,
20642045
ARRAY_SIZE(st->normal_xfer));
@@ -2080,6 +2061,10 @@ static int ad7380_probe(struct spi_device *spi)
20802061
st->seq_xfer[2].cs_change = 1;
20812062
st->seq_xfer[2].cs_change_delay.value = st->chip_info->timing_specs->t_csh_ns;
20822063
st->seq_xfer[2].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
2064+
if (st->num_sdo_lines > 1) {
2065+
st->seq_xfer[2].multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE;
2066+
st->seq_xfer[3].multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE;
2067+
}
20832068

20842069
spi_message_init_with_transfers(&st->seq_msg, st->seq_xfer,
20852070
ARRAY_SIZE(st->seq_xfer));
@@ -2108,14 +2093,6 @@ static int ad7380_probe(struct spi_device *spi)
21082093
ret = ad7380_probe_spi_offload(indio_dev, st);
21092094
if (ret)
21102095
return ret;
2111-
2112-
/* ADI tree extension to handle HDL with multiple SDI lines. */
2113-
ret = device_property_read_u32(dev, "adi,num-sdi", &st->num_sdi);
2114-
if (ret == -EINVAL)
2115-
st->num_sdi = 1; /* default */
2116-
else if (ret)
2117-
return dev_err_probe(dev, ret,
2118-
"Failed to read adi,num-sdi property\n");
21192096
}
21202097

21212098
ret = ad7380_init(st, external_ref_en);

0 commit comments

Comments
 (0)