Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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.

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>

authored by

David Lechner and committed by
Jonathan Cameron
196c9df1 63670c90

+38 -13
+38 -13
drivers/iio/adc/ad7380.c
··· 77 77 #define AD7380_CONFIG1_REFSEL BIT(1) 78 78 #define AD7380_CONFIG1_PMODE BIT(0) 79 79 80 - #define AD7380_CONFIG2_SDO2 GENMASK(9, 8) 81 - #define AD7380_CONFIG2_SDO BIT(8) 80 + #define AD7380_CONFIG2_SDO GENMASK(9, 8) 82 81 #define AD7380_CONFIG2_RESET GENMASK(7, 0) 83 82 84 83 #define AD7380_CONFIG2_RESET_SOFT 0x3C ··· 91 92 #define T_CONVERT_X_NS 500 /* xth conversion start time (oversampling) */ 92 93 #define T_POWERUP_US 5000 /* Power up */ 93 94 94 - /* 95 - * AD738x support several SDO lines to increase throughput, but driver currently 96 - * supports only 1 SDO line (standard SPI transaction) 97 - */ 98 - #define AD7380_NUM_SDO_LINES 1 99 95 #define AD7380_DEFAULT_GAIN_MILLI 1000 100 96 101 97 /* ··· 882 888 bool resolution_boost_enabled; 883 889 unsigned int ch; 884 890 bool seq; 891 + /* How many SDO lines are wired up. */ 892 + u8 num_sdo_lines; 885 893 unsigned int vref_mv; 886 894 unsigned int vcm_mv[MAX_NUM_CHANNELS]; 887 895 unsigned int gain_milli[MAX_NUM_CHANNELS]; ··· 1080 1084 if (oversampling_ratio > 1) 1081 1085 xfer.delay.value = T_CONVERT_0_NS + 1082 1086 T_CONVERT_X_NS * (oversampling_ratio - 1) * 1083 - st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES; 1087 + st->chip_info->num_simult_channels / st->num_sdo_lines; 1084 1088 1085 1089 return spi_sync_transfer(st->spi, &xfer, 1); 1086 1090 } ··· 1109 1113 if (oversampling_ratio > 1) 1110 1114 t_convert = T_CONVERT_0_NS + T_CONVERT_X_NS * 1111 1115 (oversampling_ratio - 1) * 1112 - st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES; 1116 + st->chip_info->num_simult_channels / st->num_sdo_lines; 1113 1117 1114 1118 if (st->seq) { 1115 1119 xfer[0].delay.value = xfer[1].delay.value = t_convert; ··· 1194 1198 xfer->bits_per_word = scan_type->realbits; 1195 1199 xfer->offload_flags = SPI_OFFLOAD_XFER_RX_STREAM; 1196 1200 xfer->len = AD7380_SPI_BYTES(scan_type) * st->chip_info->num_simult_channels; 1201 + if (st->num_sdo_lines > 1) 1202 + xfer->multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE; 1197 1203 1198 1204 spi_message_init_with_transfers(&st->offload_msg, xfer, 1); 1199 1205 st->offload_msg.offload = st->offload; ··· 1791 1793 1792 1794 static int ad7380_init(struct ad7380_state *st, bool external_ref_en) 1793 1795 { 1796 + u32 sdo; 1794 1797 int ret; 1795 1798 1796 1799 /* perform hard reset */ ··· 1814 1815 st->ch = 0; 1815 1816 st->seq = false; 1816 1817 1817 - /* SPI 1-wire mode */ 1818 + /* SDO field has an irregular mapping. */ 1819 + switch (st->num_sdo_lines) { 1820 + case 1: 1821 + sdo = 1; 1822 + break; 1823 + case 2: 1824 + sdo = 0; 1825 + break; 1826 + case 4: 1827 + sdo = 2; 1828 + break; 1829 + default: 1830 + return -EINVAL; 1831 + } 1832 + 1818 1833 return regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2, 1819 1834 AD7380_CONFIG2_SDO, 1820 - FIELD_PREP(AD7380_CONFIG2_SDO, 1821 - AD7380_NUM_SDO_LINES)); 1835 + FIELD_PREP(AD7380_CONFIG2_SDO, sdo)); 1822 1836 } 1823 1837 1824 1838 static int ad7380_probe_spi_offload(struct iio_dev *indio_dev, ··· 1854 1842 "failed to get offload trigger\n"); 1855 1843 1856 1844 sample_rate = st->chip_info->max_conversion_rate_hz * 1857 - AD7380_NUM_SDO_LINES / st->chip_info->num_simult_channels; 1845 + st->num_sdo_lines / st->chip_info->num_simult_channels; 1858 1846 1859 1847 st->sample_freq_range[0] = 1; /* min */ 1860 1848 st->sample_freq_range[1] = 1; /* step */ ··· 1898 1886 st->chip_info = spi_get_device_match_data(spi); 1899 1887 if (!st->chip_info) 1900 1888 return dev_err_probe(dev, -EINVAL, "missing match data\n"); 1889 + 1890 + st->num_sdo_lines = spi->num_rx_lanes; 1891 + 1892 + if (st->num_sdo_lines < 1 || st->num_sdo_lines > st->chip_info->num_simult_channels) 1893 + return dev_err_probe(dev, -EINVAL, 1894 + "invalid number of SDO lines (%d)\n", 1895 + st->num_sdo_lines); 1901 1896 1902 1897 ret = devm_regulator_bulk_get_enable(dev, st->chip_info->num_supplies, 1903 1898 st->chip_info->supplies); ··· 2029 2010 st->normal_xfer[0].cs_change_delay.value = st->chip_info->timing_specs->t_csh_ns; 2030 2011 st->normal_xfer[0].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; 2031 2012 st->normal_xfer[1].rx_buf = st->scan_data; 2013 + if (st->num_sdo_lines > 1) 2014 + st->normal_xfer[1].multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE; 2032 2015 2033 2016 spi_message_init_with_transfers(&st->normal_msg, st->normal_xfer, 2034 2017 ARRAY_SIZE(st->normal_xfer)); ··· 2052 2031 st->seq_xfer[2].cs_change = 1; 2053 2032 st->seq_xfer[2].cs_change_delay.value = st->chip_info->timing_specs->t_csh_ns; 2054 2033 st->seq_xfer[2].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; 2034 + if (st->num_sdo_lines > 1) { 2035 + st->seq_xfer[2].multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE; 2036 + st->seq_xfer[3].multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE; 2037 + } 2055 2038 2056 2039 spi_message_init_with_transfers(&st->seq_msg, st->seq_xfer, 2057 2040 ARRAY_SIZE(st->seq_xfer));