diff options
-rw-r--r-- | drivers/iio/adc/ad799x.c | 7 | ||||
-rw-r--r-- | drivers/iio/adc/ad9467.c | 374 | ||||
-rw-r--r-- | drivers/iio/adc/ad_sigma_delta.c | 6 | ||||
-rw-r--r-- | drivers/iio/adc/adi-axi-adc.c | 127 | ||||
-rw-r--r-- | drivers/iio/adc/exynos_adc.c | 16 | ||||
-rw-r--r-- | drivers/iio/adc/fsl-imx25-gcq.c | 10 | ||||
-rw-r--r-- | drivers/iio/adc/intel_mrfld_adc.c | 12 | ||||
-rw-r--r-- | drivers/iio/adc/mcp3564.c | 16 | ||||
-rw-r--r-- | drivers/iio/adc/pac1934.c | 9 | ||||
-rw-r--r-- | drivers/iio/adc/stm32-adc.c | 10 | ||||
-rw-r--r-- | drivers/iio/adc/stm32-dfsdm-adc.c | 12 | ||||
-rw-r--r-- | drivers/iio/adc/ti-ads1015.c | 5 | ||||
-rw-r--r-- | drivers/iio/adc/twl6030-gpadc.c | 8 | ||||
-rw-r--r-- | drivers/iio/common/inv_sensors/inv_sensors_timestamp.c | 33 | ||||
-rw-r--r-- | drivers/iio/dac/ad9739a.c | 5 | ||||
-rw-r--r-- | drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c | 20 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 2 | ||||
-rw-r--r-- | drivers/iio/industrialio-backend.c | 162 | ||||
-rw-r--r-- | drivers/iio/pressure/zpa2326.c | 10 | ||||
-rw-r--r-- | drivers/iio/temperature/mcp9600.c | 3 | ||||
-rw-r--r-- | include/linux/iio/backend.h | 74 | ||||
-rw-r--r-- | include/linux/iio/common/inv_sensors_timestamp.h | 3 |
22 files changed, 734 insertions, 190 deletions
diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c index b757cc45c4decf..0f0dcd9ca6b60d 100644 --- a/drivers/iio/adc/ad799x.c +++ b/drivers/iio/adc/ad799x.c @@ -128,7 +128,7 @@ struct ad799x_state { struct regulator *vref; /* lock to protect against multiple access to the device */ struct mutex lock; - unsigned id; + unsigned int id; u16 config; u8 *rx_buf; @@ -253,7 +253,7 @@ static int ad799x_update_scan_mode(struct iio_dev *indio_dev, } } -static int ad799x_scan_direct(struct ad799x_state *st, unsigned ch) +static int ad799x_scan_direct(struct ad799x_state *st, unsigned int ch) { u8 cmd; @@ -335,6 +335,7 @@ static ssize_t ad799x_read_frequency(struct device *dev, struct ad799x_state *st = iio_priv(indio_dev); int ret = i2c_smbus_read_byte_data(st->client, AD7998_CYCLE_TMR_REG); + if (ret < 0) return ret; @@ -523,7 +524,7 @@ done: return IRQ_HANDLED; } -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, +static IIO_DEV_ATTR_SAMP_FREQ(0644, ad799x_read_frequency, ad799x_write_frequency); static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("15625 7812 3906 1953 976 488 244 0"); diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c index 7475ec2a56c722..e85b763b9ffcb1 100644 --- a/drivers/iio/adc/ad9467.c +++ b/drivers/iio/adc/ad9467.c @@ -4,7 +4,11 @@ * * Copyright 2012-2020 Analog Devices Inc. */ + +#include <linux/bitmap.h> +#include <linux/bitops.h> #include <linux/cleanup.h> +#include <linux/debugfs.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/device.h> @@ -100,6 +104,8 @@ #define AD9467_DEF_OUTPUT_MODE 0x08 #define AD9467_REG_VREF_MASK 0x0F +#define AD9647_MAX_TEST_POINTS 32 + struct ad9467_chip_info { const char *name; unsigned int id; @@ -110,6 +116,9 @@ struct ad9467_chip_info { unsigned long max_rate; unsigned int default_output_mode; unsigned int vref_mask; + unsigned int num_lanes; + /* data clock output */ + bool has_dco; }; struct ad9467_state { @@ -119,7 +128,16 @@ struct ad9467_state { struct clk *clk; unsigned int output_mode; unsigned int (*scales)[2]; - + /* + * Times 2 because we may also invert the signal polarity and run the + * calibration again. For some reference on the test points (ad9265) see: + * https://www.analog.com/media/en/technical-documentation/data-sheets/ad9265.pdf + * at page 38 for the dco output delay. On devices as ad9467, the + * calibration is done at the backend level. For the ADI axi-adc: + * https://wiki.analog.com/resources/fpga/docs/axi_adc_ip + * at the io delay control section. + */ + DECLARE_BITMAP(calib_map, AD9647_MAX_TEST_POINTS * 2); struct gpio_desc *pwrdown_gpio; /* ensure consistent state obtained on multiple related accesses */ struct mutex lock; @@ -242,6 +260,7 @@ static const struct ad9467_chip_info ad9467_chip_tbl = { .num_channels = ARRAY_SIZE(ad9467_channels), .default_output_mode = AD9467_DEF_OUTPUT_MODE, .vref_mask = AD9467_REG_VREF_MASK, + .num_lanes = 8, }; static const struct ad9467_chip_info ad9434_chip_tbl = { @@ -254,6 +273,7 @@ static const struct ad9467_chip_info ad9434_chip_tbl = { .num_channels = ARRAY_SIZE(ad9434_channels), .default_output_mode = AD9434_DEF_OUTPUT_MODE, .vref_mask = AD9434_REG_VREF_MASK, + .num_lanes = 6, }; static const struct ad9467_chip_info ad9265_chip_tbl = { @@ -266,6 +286,7 @@ static const struct ad9467_chip_info ad9265_chip_tbl = { .num_channels = ARRAY_SIZE(ad9467_channels), .default_output_mode = AD9265_DEF_OUTPUT_MODE, .vref_mask = AD9265_REG_VREF_MASK, + .has_dco = true, }; static int ad9467_get_scale(struct ad9467_state *st, int *val, int *val2) @@ -321,6 +342,246 @@ static int ad9467_set_scale(struct ad9467_state *st, int val, int val2) return -EINVAL; } +static int ad9467_outputmode_set(struct spi_device *spi, unsigned int mode) +{ + int ret; + + ret = ad9467_spi_write(spi, AN877_ADC_REG_OUTPUT_MODE, mode); + if (ret < 0) + return ret; + + return ad9467_spi_write(spi, AN877_ADC_REG_TRANSFER, + AN877_ADC_TRANSFER_SYNC); +} + +static int ad9647_calibrate_prepare(const struct ad9467_state *st) +{ + struct iio_backend_data_fmt data = { + .enable = false, + }; + unsigned int c; + int ret; + + ret = ad9467_spi_write(st->spi, AN877_ADC_REG_TEST_IO, + AN877_ADC_TESTMODE_PN9_SEQ); + if (ret) + return ret; + + ret = ad9467_spi_write(st->spi, AN877_ADC_REG_TRANSFER, + AN877_ADC_TRANSFER_SYNC); + if (ret) + return ret; + + ret = ad9467_outputmode_set(st->spi, st->info->default_output_mode); + if (ret) + return ret; + + for (c = 0; c < st->info->num_channels; c++) { + ret = iio_backend_data_format_set(st->back, c, &data); + if (ret) + return ret; + } + + ret = iio_backend_test_pattern_set(st->back, 0, + IIO_BACKEND_ADI_PRBS_9A); + if (ret) + return ret; + + return iio_backend_chan_enable(st->back, 0); +} + +static int ad9647_calibrate_polarity_set(const struct ad9467_state *st, + bool invert) +{ + enum iio_backend_sample_trigger trigger; + + if (st->info->has_dco) { + unsigned int phase = AN877_ADC_OUTPUT_EVEN_ODD_MODE_EN; + + if (invert) + phase |= AN877_ADC_INVERT_DCO_CLK; + + return ad9467_spi_write(st->spi, AN877_ADC_REG_OUTPUT_PHASE, + phase); + } + + if (invert) + trigger = IIO_BACKEND_SAMPLE_TRIGGER_EDGE_FALLING; + else + trigger = IIO_BACKEND_SAMPLE_TRIGGER_EDGE_RISING; + + return iio_backend_data_sample_trigger(st->back, trigger); +} + +/* + * The idea is pretty simple. Find the max number of successful points in a row + * and get the one in the middle. + */ +static unsigned int ad9467_find_optimal_point(const unsigned long *calib_map, + unsigned int start, + unsigned int nbits, + unsigned int *val) +{ + unsigned int bit = start, end, start_cnt, cnt = 0; + + for_each_clear_bitrange_from(bit, end, calib_map, nbits + start) { + if (end - bit > cnt) { + cnt = end - bit; + start_cnt = bit; + } + } + + if (cnt) + *val = start_cnt + cnt / 2; + + return cnt; +} + +static int ad9467_calibrate_apply(const struct ad9467_state *st, + unsigned int val) +{ + unsigned int lane; + int ret; + + if (st->info->has_dco) { + ret = ad9467_spi_write(st->spi, AN877_ADC_REG_OUTPUT_DELAY, + val); + if (ret) + return ret; + + return ad9467_spi_write(st->spi, AN877_ADC_REG_TRANSFER, + AN877_ADC_TRANSFER_SYNC); + } + + for (lane = 0; lane < st->info->num_lanes; lane++) { + ret = iio_backend_iodelay_set(st->back, lane, val); + if (ret) + return ret; + } + + return 0; +} + +static int ad9647_calibrate_stop(const struct ad9467_state *st) +{ + struct iio_backend_data_fmt data = { + .sign_extend = true, + .enable = true, + }; + unsigned int c, mode; + int ret; + + ret = iio_backend_chan_disable(st->back, 0); + if (ret) + return ret; + + ret = iio_backend_test_pattern_set(st->back, 0, + IIO_BACKEND_NO_TEST_PATTERN); + if (ret) + return ret; + + for (c = 0; c < st->info->num_channels; c++) { + ret = iio_backend_data_format_set(st->back, c, &data); + if (ret) + return ret; + } + + mode = st->info->default_output_mode | AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT; + ret = ad9467_outputmode_set(st->spi, mode); + if (ret) + return ret; + + ret = ad9467_spi_write(st->spi, AN877_ADC_REG_TEST_IO, + AN877_ADC_TESTMODE_OFF); + if (ret) + return ret; + + return ad9467_spi_write(st->spi, AN877_ADC_REG_TRANSFER, + AN877_ADC_TRANSFER_SYNC); +} + +static int ad9467_calibrate(struct ad9467_state *st) +{ + unsigned int point, val, inv_val, cnt, inv_cnt = 0; + /* + * Half of the bitmap is for the inverted signal. The number of test + * points is the same though... + */ + unsigned int test_points = AD9647_MAX_TEST_POINTS; + unsigned long sample_rate = clk_get_rate(st->clk); + struct device *dev = &st->spi->dev; + bool invert = false, stat; + int ret; + + /* all points invalid */ + bitmap_fill(st->calib_map, BITS_PER_TYPE(st->calib_map)); + + ret = ad9647_calibrate_prepare(st); + if (ret) + return ret; +retune: + ret = ad9647_calibrate_polarity_set(st, invert); + if (ret) + return ret; + + for (point = 0; point < test_points; point++) { + ret = ad9467_calibrate_apply(st, point); + if (ret) + return ret; + + ret = iio_backend_chan_status(st->back, 0, &stat); + if (ret) + return ret; + + __assign_bit(point + invert * test_points, st->calib_map, stat); + } + + if (!invert) { + cnt = ad9467_find_optimal_point(st->calib_map, 0, test_points, + &val); + /* + * We're happy if we find, at least, three good test points in + * a row. + */ + if (cnt < 3) { + invert = true; + goto retune; + } + } else { + inv_cnt = ad9467_find_optimal_point(st->calib_map, test_points, + test_points, &inv_val); + if (!inv_cnt && !cnt) + return -EIO; + } + + if (inv_cnt < cnt) { + ret = ad9647_calibrate_polarity_set(st, false); + if (ret) + return ret; + } else { + /* + * polarity inverted is the last test to run. Hence, there's no + * need to re-do any configuration. We just need to "normalize" + * the selected value. + */ + val = inv_val - test_points; + } + + if (st->info->has_dco) + dev_dbg(dev, "%sDCO 0x%X CLK %lu Hz\n", inv_cnt >= cnt ? "INVERT " : "", + val, sample_rate); + else + dev_dbg(dev, "%sIDELAY 0x%x\n", inv_cnt >= cnt ? "INVERT " : "", + val); + + ret = ad9467_calibrate_apply(st, val); + if (ret) + return ret; + + /* finally apply the optimal value */ + return ad9647_calibrate_stop(st); +} + static int ad9467_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long m) @@ -345,7 +606,9 @@ static int ad9467_write_raw(struct iio_dev *indio_dev, { struct ad9467_state *st = iio_priv(indio_dev); const struct ad9467_chip_info *info = st->info; + unsigned long sample_rate; long r_clk; + int ret; switch (mask) { case IIO_CHAN_INFO_SCALE: @@ -358,7 +621,23 @@ static int ad9467_write_raw(struct iio_dev *indio_dev, return -EINVAL; } - return clk_set_rate(st->clk, r_clk); + sample_rate = clk_get_rate(st->clk); + /* + * clk_set_rate() would also do this but since we would still + * need it for avoiding an unnecessary calibration, do it now. + */ + if (sample_rate == r_clk) + return 0; + + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { + ret = clk_set_rate(st->clk, r_clk); + if (ret) + return ret; + + guard(mutex)(&st->lock); + ret = ad9467_calibrate(st); + } + return ret; default: return -EINVAL; } @@ -411,18 +690,6 @@ static const struct iio_info ad9467_info = { .read_avail = ad9467_read_avail, }; -static int ad9467_outputmode_set(struct spi_device *spi, unsigned int mode) -{ - int ret; - - ret = ad9467_spi_write(spi, AN877_ADC_REG_OUTPUT_MODE, mode); - if (ret < 0) - return ret; - - return ad9467_spi_write(spi, AN877_ADC_REG_TRANSFER, - AN877_ADC_TRANSFER_SYNC); -} - static int ad9467_scale_fill(struct ad9467_state *st) { const struct ad9467_chip_info *info = st->info; @@ -442,29 +709,6 @@ static int ad9467_scale_fill(struct ad9467_state *st) return 0; } -static int ad9467_setup(struct ad9467_state *st) -{ - struct iio_backend_data_fmt data = { - .sign_extend = true, - .enable = true, - }; - unsigned int c, mode; - int ret; - - mode = st->info->default_output_mode | AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT; - ret = ad9467_outputmode_set(st->spi, mode); - if (ret) - return ret; - - for (c = 0; c < st->info->num_channels; c++) { - ret = iio_backend_data_format_set(st->back, c, &data); - if (ret) - return ret; - } - - return 0; -} - static int ad9467_reset(struct device *dev) { struct gpio_desc *gpio; @@ -521,6 +765,52 @@ static int ad9467_iio_backend_get(struct ad9467_state *st) return -ENODEV; } +static ssize_t ad9467_dump_calib_table(struct file *file, + char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct ad9467_state *st = file->private_data; + unsigned int bit, size = BITS_PER_TYPE(st->calib_map); + /* +2 for the newline and +1 for the string termination */ + unsigned char map[AD9647_MAX_TEST_POINTS * 2 + 3]; + ssize_t len = 0; + + guard(mutex)(&st->lock); + if (*ppos) + goto out_read; + + for (bit = 0; bit < size; bit++) { + if (bit == size / 2) + len += scnprintf(map + len, sizeof(map) - len, "\n"); + + len += scnprintf(map + len, sizeof(map) - len, "%c", + test_bit(bit, st->calib_map) ? 'x' : 'o'); + } + + len += scnprintf(map + len, sizeof(map) - len, "\n"); +out_read: + return simple_read_from_buffer(userbuf, count, ppos, map, len); +} + +static const struct file_operations ad9467_calib_table_fops = { + .open = simple_open, + .read = ad9467_dump_calib_table, + .llseek = default_llseek, + .owner = THIS_MODULE, +}; + +static void ad9467_debugfs_init(struct iio_dev *indio_dev) +{ + struct dentry *d = iio_get_debugfs_dentry(indio_dev); + struct ad9467_state *st = iio_priv(indio_dev); + + if (!IS_ENABLED(CONFIG_DEBUG_FS)) + return; + + debugfs_create_file("calibration_table_dump", 0400, d, st, + &ad9467_calib_table_fops); +} + static int ad9467_probe(struct spi_device *spi) { struct iio_dev *indio_dev; @@ -580,11 +870,17 @@ static int ad9467_probe(struct spi_device *spi) if (ret) return ret; - ret = ad9467_setup(st); + ret = ad9467_calibrate(st); + if (ret) + return ret; + + ret = devm_iio_device_register(&spi->dev, indio_dev); if (ret) return ret; - return devm_iio_device_register(&spi->dev, indio_dev); + ad9467_debugfs_init(indio_dev); + + return 0; } static const struct of_device_id ad9467_of_match[] = { diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index 97a05f325df7cf..a2b87f6b7a071d 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -206,7 +206,7 @@ int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta, unsigned int mode, unsigned int channel) { int ret; - unsigned long timeout; + unsigned long time_left; ret = ad_sigma_delta_set_channel(sigma_delta, channel); if (ret) @@ -223,8 +223,8 @@ int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta, sigma_delta->irq_dis = false; enable_irq(sigma_delta->irq_line); - timeout = wait_for_completion_timeout(&sigma_delta->completion, 2 * HZ); - if (timeout == 0) { + time_left = wait_for_completion_timeout(&sigma_delta->completion, 2 * HZ); + if (time_left == 0) { sigma_delta->irq_dis = true; disable_irq_nosync(sigma_delta->irq_line); ret = -EIO; diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c index 9444b0c5a93c6a..0cf0d81358fd58 100644 --- a/drivers/iio/adc/adi-axi-adc.c +++ b/drivers/iio/adc/adi-axi-adc.c @@ -7,11 +7,13 @@ */ #include <linux/bitfield.h> +#include <linux/cleanup.h> #include <linux/clk.h> #include <linux/err.h> #include <linux/io.h> #include <linux/delay.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/property.h> @@ -37,6 +39,9 @@ #define ADI_AXI_REG_RSTN_MMCM_RSTN BIT(1) #define ADI_AXI_REG_RSTN_RSTN BIT(0) +#define ADI_AXI_ADC_REG_CTRL 0x0044 +#define ADI_AXI_ADC_CTRL_DDR_EDGESEL_MASK BIT(1) + /* ADC Channel controls */ #define ADI_AXI_REG_CHAN_CTRL(c) (0x0400 + (c) * 0x40) @@ -51,14 +56,28 @@ #define ADI_AXI_REG_CHAN_CTRL_PN_TYPE_OWR BIT(1) #define ADI_AXI_REG_CHAN_CTRL_ENABLE BIT(0) +#define ADI_AXI_ADC_REG_CHAN_STATUS(c) (0x0404 + (c) * 0x40) +#define ADI_AXI_ADC_CHAN_STAT_PN_MASK GENMASK(2, 1) + +#define ADI_AXI_ADC_REG_CHAN_CTRL_3(c) (0x0418 + (c) * 0x40) +#define ADI_AXI_ADC_CHAN_PN_SEL_MASK GENMASK(19, 16) + +/* IO Delays */ +#define ADI_AXI_ADC_REG_DELAY(l) (0x0800 + (l) * 0x4) +#define AXI_ADC_DELAY_CTRL_MASK GENMASK(4, 0) + +#define ADI_AXI_ADC_MAX_IO_NUM_LANES 15 + #define ADI_AXI_REG_CHAN_CTRL_DEFAULTS \ (ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT | \ ADI_AXI_REG_CHAN_CTRL_FMT_EN | \ ADI_AXI_REG_CHAN_CTRL_ENABLE) struct adi_axi_adc_state { - struct regmap *regmap; - struct device *dev; + struct regmap *regmap; + struct device *dev; + /* lock to protect multiple accesses to the device registers */ + struct mutex lock; }; static int axi_adc_enable(struct iio_backend *back) @@ -104,6 +123,100 @@ static int axi_adc_data_format_set(struct iio_backend *back, unsigned int chan, ADI_AXI_REG_CHAN_CTRL_FMT_MASK, val); } +static int axi_adc_data_sample_trigger(struct iio_backend *back, + enum iio_backend_sample_trigger trigger) +{ + struct adi_axi_adc_state *st = iio_backend_get_priv(back); + + switch (trigger) { + case IIO_BACKEND_SAMPLE_TRIGGER_EDGE_RISING: + return regmap_clear_bits(st->regmap, ADI_AXI_ADC_REG_CTRL, + ADI_AXI_ADC_CTRL_DDR_EDGESEL_MASK); + case IIO_BACKEND_SAMPLE_TRIGGER_EDGE_FALLING: + return regmap_set_bits(st->regmap, ADI_AXI_ADC_REG_CTRL, + ADI_AXI_ADC_CTRL_DDR_EDGESEL_MASK); + default: + return -EINVAL; + } +} + +static int axi_adc_iodelays_set(struct iio_backend *back, unsigned int lane, + unsigned int tap) +{ + struct adi_axi_adc_state *st = iio_backend_get_priv(back); + int ret; + u32 val; + + if (tap > FIELD_MAX(AXI_ADC_DELAY_CTRL_MASK)) + return -EINVAL; + if (lane > ADI_AXI_ADC_MAX_IO_NUM_LANES) + return -EINVAL; + + guard(mutex)(&st->lock); + ret = regmap_write(st->regmap, ADI_AXI_ADC_REG_DELAY(lane), tap); + if (ret) + return ret; + /* + * If readback is ~0, that means there are issues with the + * delay_clk. + */ + ret = regmap_read(st->regmap, ADI_AXI_ADC_REG_DELAY(lane), &val); + if (ret) + return ret; + if (val == U32_MAX) + return -EIO; + + return 0; +} + +static int axi_adc_test_pattern_set(struct iio_backend *back, + unsigned int chan, + enum iio_backend_test_pattern pattern) +{ + struct adi_axi_adc_state *st = iio_backend_get_priv(back); + + switch (pattern) { + case IIO_BACKEND_NO_TEST_PATTERN: + /* nothing to do */ + return 0; + case IIO_BACKEND_ADI_PRBS_9A: + return regmap_update_bits(st->regmap, ADI_AXI_ADC_REG_CHAN_CTRL_3(chan), + ADI_AXI_ADC_CHAN_PN_SEL_MASK, + FIELD_PREP(ADI_AXI_ADC_CHAN_PN_SEL_MASK, 0)); + default: + return -EINVAL; + } +} + +static int axi_adc_chan_status(struct iio_backend *back, unsigned int chan, + bool *error) +{ + struct adi_axi_adc_state *st = iio_backend_get_priv(back); + int ret; + u32 val; + + guard(mutex)(&st->lock); + /* reset test bits by setting them */ + ret = regmap_write(st->regmap, ADI_AXI_ADC_REG_CHAN_STATUS(chan), + ADI_AXI_ADC_CHAN_STAT_PN_MASK); + if (ret) + return ret; + + /* let's give enough time to validate or erroring the incoming pattern */ + fsleep(1000); + + ret = regmap_read(st->regmap, ADI_AXI_ADC_REG_CHAN_STATUS(chan), &val); + if (ret) + return ret; + + if (ADI_AXI_ADC_CHAN_STAT_PN_MASK & val) + *error = true; + else + *error = false; + + return 0; +} + static int axi_adc_chan_enable(struct iio_backend *back, unsigned int chan) { struct adi_axi_adc_state *st = iio_backend_get_priv(back); @@ -142,7 +255,6 @@ static const struct regmap_config axi_adc_regmap_config = { .val_bits = 32, .reg_bits = 32, .reg_stride = 4, - .max_register = 0x0800, }; static const struct iio_backend_ops adi_axi_adc_generic = { @@ -153,6 +265,10 @@ static const struct iio_backend_ops adi_axi_adc_generic = { .chan_disable = axi_adc_chan_disable, .request_buffer = axi_adc_request_buffer, .free_buffer = axi_adc_free_buffer, + .data_sample_trigger = axi_adc_data_sample_trigger, + .iodelay_set = axi_adc_iodelays_set, + .test_pattern_set = axi_adc_test_pattern_set, + .chan_status = axi_adc_chan_status, }; static int adi_axi_adc_probe(struct platform_device *pdev) @@ -161,6 +277,7 @@ static int adi_axi_adc_probe(struct platform_device *pdev) struct adi_axi_adc_state *st; void __iomem *base; unsigned int ver; + struct clk *clk; int ret; st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL); @@ -181,6 +298,10 @@ static int adi_axi_adc_probe(struct platform_device *pdev) if (!expected_ver) return -ENODEV; + clk = devm_clk_get_enabled(&pdev->dev, NULL); + if (IS_ERR(clk)) + return PTR_ERR(clk); + /* * Force disable the core. Up to the frontend to enable us. And we can * still read/write registers... diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c index 614de96448003e..78fada4b7b1c86 100644 --- a/drivers/iio/adc/exynos_adc.c +++ b/drivers/iio/adc/exynos_adc.c @@ -538,7 +538,7 @@ static int exynos_read_raw(struct iio_dev *indio_dev, long mask) { struct exynos_adc *info = iio_priv(indio_dev); - unsigned long timeout; + unsigned long time_left; int ret; if (mask == IIO_CHAN_INFO_SCALE) { @@ -562,9 +562,9 @@ static int exynos_read_raw(struct iio_dev *indio_dev, if (info->data->start_conv) info->data->start_conv(info, chan->address); - timeout = wait_for_completion_timeout(&info->completion, - EXYNOS_ADC_TIMEOUT); - if (timeout == 0) { + time_left = wait_for_completion_timeout(&info->completion, + EXYNOS_ADC_TIMEOUT); + if (time_left == 0) { dev_warn(&indio_dev->dev, "Conversion timed out! Resetting\n"); if (info->data->init_hw) info->data->init_hw(info); @@ -583,7 +583,7 @@ static int exynos_read_raw(struct iio_dev *indio_dev, static int exynos_read_s3c64xx_ts(struct iio_dev *indio_dev, int *x, int *y) { struct exynos_adc *info = iio_priv(indio_dev); - unsigned long timeout; + unsigned long time_left; int ret; mutex_lock(&info->lock); @@ -597,9 +597,9 @@ static int exynos_read_s3c64xx_ts(struct iio_dev *indio_dev, int *x, int *y) /* Select the ts channel to be used and Trigger conversion */ info->data->start_conv(info, ADC_S3C2410_MUX_TS); - timeout = wait_for_completion_timeout(&info->completion, - EXYNOS_ADC_TIMEOUT); - if (timeout == 0) { + time_left = wait_for_completion_timeout(&info->completion, + EXYNOS_ADC_TIMEOUT); + if (time_left == 0) { dev_warn(&indio_dev->dev, "Conversion timed out! Resetting\n"); if (info->data->init_hw) info->data->init_hw(info); diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c index 394396b916309e..b680690631dbb7 100644 --- a/drivers/iio/adc/fsl-imx25-gcq.c +++ b/drivers/iio/adc/fsl-imx25-gcq.c @@ -108,7 +108,7 @@ static int mx25_gcq_get_raw_value(struct device *dev, struct mx25_gcq_priv *priv, int *val) { - long timeout; + long time_left; u32 data; /* Setup the configuration we want to use */ @@ -121,12 +121,12 @@ static int mx25_gcq_get_raw_value(struct device *dev, regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS, MX25_ADCQ_CR_FQS); - timeout = wait_for_completion_interruptible_timeout( + time_left = wait_for_completion_interruptible_timeout( &priv->completed, MX25_GCQ_TIMEOUT); - if (timeout < 0) { + if (time_left < 0) { dev_err(dev, "ADC wait for measurement failed\n"); - return timeout; - } else if (timeout == 0) { + return time_left; + } else if (time_left == 0) { dev_err(dev, "ADC timed out\n"); return -ETIMEDOUT; } diff --git a/drivers/iio/adc/intel_mrfld_adc.c b/drivers/iio/adc/intel_mrfld_adc.c index 7263ad76124d70..c7f40ae6e6089a 100644 --- a/drivers/iio/adc/intel_mrfld_adc.c +++ b/drivers/iio/adc/intel_mrfld_adc.c @@ -75,7 +75,7 @@ static int mrfld_adc_single_conv(struct iio_dev *indio_dev, struct mrfld_adc *adc = iio_priv(indio_dev); struct regmap *regmap = adc->regmap; unsigned int req; - long timeout; + long time_left; __be16 value; int ret; @@ -95,13 +95,13 @@ static int mrfld_adc_single_conv(struct iio_dev *indio_dev, if (ret) goto done; - timeout = wait_for_completion_interruptible_timeout(&adc->completion, - BCOVE_ADC_TIMEOUT); - if (timeout < 0) { - ret = timeout; + time_left = wait_for_completion_interruptible_timeout(&adc->completion, + BCOVE_ADC_TIMEOUT); + if (time_left < 0) { + ret = time_left; goto done; } - if (timeout == 0) { + if (time_left == 0) { ret = -ETIMEDOUT; goto done; } diff --git a/drivers/iio/adc/mcp3564.c b/drivers/iio/adc/mcp3564.c index 311b613b605754..e2ae13f1e842e8 100644 --- a/drivers/iio/adc/mcp3564.c +++ b/drivers/iio/adc/mcp3564.c @@ -998,7 +998,6 @@ static int mcp3564_parse_fw_children(struct iio_dev *indio_dev) struct mcp3564_state *adc = iio_priv(indio_dev); struct device *dev = &adc->spi->dev; struct iio_chan_spec *channels; - struct fwnode_handle *child; struct iio_chan_spec chanspec = mcp3564_channel_template; struct iio_chan_spec temp_chanspec = mcp3564_temp_channel_template; struct iio_chan_spec burnout_chanspec = mcp3564_burnout_channel_template; @@ -1025,7 +1024,7 @@ static int mcp3564_parse_fw_children(struct iio_dev *indio_dev) if (!channels) return dev_err_probe(dev, -ENOMEM, "Can't allocate memory\n"); - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { node_name = fwnode_get_name(child); if (fwnode_property_present(child, "diff-channels")) { @@ -1033,26 +1032,25 @@ static int mcp3564_parse_fw_children(struct iio_dev *indio_dev) "diff-channels", inputs, ARRAY_SIZE(inputs)); + if (ret) + return ret; + chanspec.differential = 1; } else { ret = fwnode_property_read_u32(child, "reg", &inputs[0]); + if (ret) + return ret; chanspec.differential = 0; inputs[1] = MCP3564_AGND; } - if (ret) { - fwnode_handle_put(child); - return ret; - } if (inputs[0] > MCP3564_INTERNAL_VCM || - inputs[1] > MCP3564_INTERNAL_VCM) { - fwnode_handle_put(child); + inputs[1] > MCP3564_INTERNAL_VCM) return dev_err_probe(&indio_dev->dev, -EINVAL, "Channel index > %d, for %s\n", MCP3564_INTERNAL_VCM + 1, node_name); - } chanspec.address = (inputs[0] << 4) | inputs[1]; chanspec.channel = inputs[0]; diff --git a/drivers/iio/adc/pac1934.c b/drivers/iio/adc/pac1934.c index f751260605e4e1..456f12faa34807 100644 --- a/drivers/iio/adc/pac1934.c +++ b/drivers/iio/adc/pac1934.c @@ -787,6 +787,15 @@ static int pac1934_read_raw(struct iio_dev *indio_dev, s64 curr_energy; int ret, channel = chan->channel - 1; + /* + * For AVG the index should be between 5 to 8. + * To calculate PAC1934_CH_VOLTAGE_AVERAGE, + * respectively PAC1934_CH_CURRENT real index, we need + * to remove the added offset (PAC1934_MAX_NUM_CHANNELS). + */ + if (channel >= PAC1934_MAX_NUM_CHANNELS) + channel = channel - PAC1934_MAX_NUM_CHANNELS; + ret = pac1934_retrieve_data(info, PAC1934_MIN_UPDATE_WAIT_TIME_US); if (ret < 0) return ret; diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 36add95212c370..375aa7720f8042 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -1408,7 +1408,7 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev, struct stm32_adc *adc = iio_priv(indio_dev); struct device *dev = indio_dev->dev.parent; const struct stm32_adc_regspec *regs = adc->cfg->regs; - long timeout; + long time_left; u32 val; int ret; @@ -1440,12 +1440,12 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev, adc->cfg->start_conv(indio_dev, false); - timeout = wait_for_completion_interruptible_timeout( + time_left = wait_for_completion_interruptible_timeout( &adc->completion, STM32_ADC_TIMEOUT); - if (timeout == 0) { + if (time_left == 0) { ret = -ETIMEDOUT; - } else if (timeout < 0) { - ret = timeout; + } else if (time_left < 0) { + ret = time_left; } else { *res = adc->buffer[0]; ret = IIO_VAL_INT; diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index ca08ae3108b220..9a47d2c87f05a3 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -1116,7 +1116,7 @@ static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, int *res) { struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); - long timeout; + long time_left; int ret; reinit_completion(&adc->completion); @@ -1141,17 +1141,17 @@ static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev, goto stop_dfsdm; } - timeout = wait_for_completion_interruptible_timeout(&adc->completion, - DFSDM_TIMEOUT); + time_left = wait_for_completion_interruptible_timeout(&adc->completion, + DFSDM_TIMEOUT); /* Mask IRQ for regular conversion achievement*/ regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR2(adc->fl_id), DFSDM_CR2_REOCIE_MASK, DFSDM_CR2_REOCIE(0)); - if (timeout == 0) + if (time_left == 0) ret = -ETIMEDOUT; - else if (timeout < 0) - ret = timeout; + else if (time_left < 0) + ret = time_left; else ret = IIO_VAL_INT; diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c index 6ae967e4d8fa76..d3363d02f2921a 100644 --- a/drivers/iio/adc/ti-ads1015.c +++ b/drivers/iio/adc/ti-ads1015.c @@ -902,10 +902,9 @@ static int ads1015_client_get_channels_config(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); struct ads1015_data *data = iio_priv(indio_dev); struct device *dev = &client->dev; - struct fwnode_handle *node; int i = -1; - device_for_each_child_node(dev, node) { + device_for_each_child_node_scoped(dev, node) { u32 pval; unsigned int channel; unsigned int pga = ADS1015_DEFAULT_PGA; @@ -927,7 +926,6 @@ static int ads1015_client_get_channels_config(struct i2c_client *client) pga = pval; if (pga > 5) { dev_err(dev, "invalid gain on %pfw\n", node); - fwnode_handle_put(node); return -EINVAL; } } @@ -936,7 +934,6 @@ static int ads1015_client_get_channels_config(struct i2c_client *client) data_rate = pval; if (data_rate > 7) { dev_err(dev, "invalid data_rate on %pfw\n", node); - fwnode_handle_put(node); return -EINVAL; } } diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c index 78bf55438b2c67..6a3db2bce46090 100644 --- a/drivers/iio/adc/twl6030-gpadc.c +++ b/drivers/iio/adc/twl6030-gpadc.c @@ -519,7 +519,7 @@ static int twl6030_gpadc_read_raw(struct iio_dev *indio_dev, { struct twl6030_gpadc_data *gpadc = iio_priv(indio_dev); int ret; - long timeout; + long time_left; mutex_lock(&gpadc->lock); @@ -529,12 +529,12 @@ static int twl6030_gpadc_read_raw(struct iio_dev *indio_dev, goto err; } /* wait for conversion to complete */ - timeout = wait_for_completion_interruptible_timeout( + time_left = wait_for_completion_interruptible_timeout( &gpadc->irq_complete, msecs_to_jiffies(5000)); - if (timeout == 0) { + if (time_left == 0) { ret = -ETIMEDOUT; goto err; - } else if (timeout < 0) { + } else if (time_left < 0) { ret = -EINTR; goto err; } diff --git a/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c index 3b0f9598a7c773..fa205f17bd905f 100644 --- a/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c +++ b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c @@ -70,13 +70,13 @@ int inv_sensors_timestamp_update_odr(struct inv_sensors_timestamp *ts, } EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_update_odr, IIO_INV_SENSORS_TIMESTAMP); -static bool inv_validate_period(struct inv_sensors_timestamp *ts, uint32_t period, uint32_t mult) +static bool inv_validate_period(struct inv_sensors_timestamp *ts, uint32_t period) { uint32_t period_min, period_max; /* check that period is acceptable */ - period_min = ts->min_period * mult; - period_max = ts->max_period * mult; + period_min = ts->min_period * ts->mult; + period_max = ts->max_period * ts->mult; if (period > period_min && period < period_max) return true; else @@ -84,15 +84,15 @@ static bool inv_validate_period(struct inv_sensors_timestamp *ts, uint32_t perio } static bool inv_update_chip_period(struct inv_sensors_timestamp *ts, - uint32_t mult, uint32_t period) + uint32_t period) { uint32_t new_chip_period; - if (!inv_validate_period(ts, period, mult)) + if (!inv_validate_period(ts, period)) return false; /* update chip internal period estimation */ - new_chip_period = period / mult; + new_chip_period = period / ts->mult; inv_update_acc(&ts->chip_period, new_chip_period); ts->period = ts->mult * ts->chip_period.val; @@ -101,6 +101,9 @@ static bool inv_update_chip_period(struct inv_sensors_timestamp *ts, static void inv_align_timestamp_it(struct inv_sensors_timestamp *ts) { + const int64_t period_min = ts->min_period * ts->mult; + const int64_t period_max = ts->max_period * ts->mult; + int64_t add_max, sub_max; int64_t delta, jitter; int64_t adjust; @@ -108,11 +111,13 @@ static void inv_align_timestamp_it(struct inv_sensors_timestamp *ts) delta = ts->it.lo - ts->timestamp; /* adjust timestamp while respecting jitter */ + add_max = period_max - (int64_t)ts->period; + sub_max = period_min - (int64_t)ts->period; jitter = INV_SENSORS_TIMESTAMP_JITTER((int64_t)ts->period, ts->chip.jitter); if (delta > jitter) - adjust = jitter; + adjust = add_max; else if (delta < -jitter) - adjust = -jitter; + adjust = sub_max; else adjust = 0; @@ -120,16 +125,14 @@ static void inv_align_timestamp_it(struct inv_sensors_timestamp *ts) } void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts, - uint32_t fifo_period, size_t fifo_nb, - size_t sensor_nb, int64_t timestamp) + size_t sample_nb, int64_t timestamp) { struct inv_sensors_timestamp_interval *it; int64_t delta, interval; - const uint32_t fifo_mult = fifo_period / ts->chip.clock_period; uint32_t period; bool valid = false; - if (fifo_nb == 0) + if (sample_nb == 0) return; /* update interrupt timestamp and compute chip and sensor periods */ @@ -139,14 +142,14 @@ void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts, delta = it->up - it->lo; if (it->lo != 0) { /* compute period: delta time divided by number of samples */ - period = div_s64(delta, fifo_nb); - valid = inv_update_chip_period(ts, fifo_mult, period); + period = div_s64(delta, sample_nb); + valid = inv_update_chip_period(ts, period); } /* no previous data, compute theoritical value from interrupt */ if (ts->timestamp == 0) { /* elapsed time: sensor period * sensor samples number */ - interval = (int64_t)ts->period * (int64_t)sensor_nb; + interval = (int64_t)ts->period * (int64_t)sample_nb; ts->timestamp = it->up - interval; return; } diff --git a/drivers/iio/dac/ad9739a.c b/drivers/iio/dac/ad9739a.c index ff33120075bf60..f56eabe5372356 100644 --- a/drivers/iio/dac/ad9739a.c +++ b/drivers/iio/dac/ad9739a.c @@ -45,6 +45,7 @@ #define AD9739A_REG_MU_DUTY 0x25 #define AD9739A_REG_MU_CNT1 0x26 #define AD9739A_MU_EN_MASK BIT(0) +#define AD9739A_MU_GAIN_MASK BIT(1) #define AD9739A_REG_MU_CNT2 0x27 #define AD9739A_REG_MU_CNT3 0x28 #define AD9739A_REG_MU_CNT4 0x29 @@ -220,8 +221,8 @@ static int ad9739a_init(struct device *dev, const struct ad9739a_state *st) return ret; /* Enable the Mu controller search and track mode. */ - ret = regmap_set_bits(st->regmap, AD9739A_REG_MU_CNT1, - AD9739A_MU_EN_MASK); + ret = regmap_write(st->regmap, AD9739A_REG_MU_CNT1, + AD9739A_MU_EN_MASK | AD9739A_MU_GAIN_MASK); if (ret) return ret; diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c index cfb4a41ab7c11e..63b85ec88c131f 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c @@ -512,20 +512,20 @@ int inv_icm42600_buffer_fifo_parse(struct inv_icm42600_state *st) return 0; /* handle gyroscope timestamp and FIFO data parsing */ - ts = &gyro_st->ts; - inv_sensors_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total, - st->fifo.nb.gyro, st->timestamp.gyro); if (st->fifo.nb.gyro > 0) { + ts = &gyro_st->ts; + inv_sensors_timestamp_interrupt(ts, st->fifo.nb.gyro, + st->timestamp.gyro); ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro); if (ret) return ret; } /* handle accelerometer timestamp and FIFO data parsing */ - ts = &accel_st->ts; - inv_sensors_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total, - st->fifo.nb.accel, st->timestamp.accel); if (st->fifo.nb.accel > 0) { + ts = &accel_st->ts; + inv_sensors_timestamp_interrupt(ts, st->fifo.nb.accel, + st->timestamp.accel); ret = inv_icm42600_accel_parse_fifo(st->indio_accel); if (ret) return ret; @@ -555,9 +555,7 @@ int inv_icm42600_buffer_hwfifo_flush(struct inv_icm42600_state *st, if (st->fifo.nb.gyro > 0) { ts = &gyro_st->ts; - inv_sensors_timestamp_interrupt(ts, st->fifo.period, - st->fifo.nb.total, st->fifo.nb.gyro, - gyro_ts); + inv_sensors_timestamp_interrupt(ts, st->fifo.nb.gyro, gyro_ts); ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro); if (ret) return ret; @@ -565,9 +563,7 @@ int inv_icm42600_buffer_hwfifo_flush(struct inv_icm42600_state *st, if (st->fifo.nb.accel > 0) { ts = &accel_st->ts; - inv_sensors_timestamp_interrupt(ts, st->fifo.period, - st->fifo.nb.total, st->fifo.nb.accel, - accel_ts); + inv_sensors_timestamp_interrupt(ts, st->fifo.nb.accel, accel_ts); ret = inv_icm42600_accel_parse_fifo(st->indio_accel); if (ret) return ret; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c index 86465226f7e106..0dc0f22a558279 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c @@ -100,7 +100,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) goto end_session; /* Each FIFO data contains all sensors, so same number for FIFO and sensor data */ fifo_period = NSEC_PER_SEC / INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider); - inv_sensors_timestamp_interrupt(&st->timestamp, fifo_period, nb, nb, pf->timestamp); + inv_sensors_timestamp_interrupt(&st->timestamp, nb, pf->timestamp); inv_sensors_timestamp_apply_odr(&st->timestamp, fifo_period, nb, 0); /* clear internal data buffer for avoiding kernel data leak */ diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c index f08ed6d70ae590..929aff4040edd2 100644 --- a/drivers/iio/industrialio-backend.c +++ b/drivers/iio/industrialio-backend.c @@ -115,8 +115,8 @@ static DEFINE_MUTEX(iio_back_lock); /** * iio_backend_chan_enable - Enable a backend channel - * @back: Backend device - * @chan: Channel number + * @back: Backend device + * @chan: Channel number * * RETURNS: * 0 on success, negative error number on failure. @@ -129,8 +129,8 @@ EXPORT_SYMBOL_NS_GPL(iio_backend_chan_enable, IIO_BACKEND); /** * iio_backend_chan_disable - Disable a backend channel - * @back: Backend device - * @chan: Channel number + * @back: Backend device + * @chan: Channel number * * RETURNS: * 0 on success, negative error number on failure. @@ -148,8 +148,8 @@ static void __iio_backend_disable(void *back) /** * devm_iio_backend_enable - Device managed backend enable - * @dev: Consumer device for the backend - * @back: Backend device + * @dev: Consumer device for the backend + * @back: Backend device * * RETURNS: * 0 on success, negative error number on failure. @@ -168,9 +168,9 @@ EXPORT_SYMBOL_NS_GPL(devm_iio_backend_enable, IIO_BACKEND); /** * iio_backend_data_format_set - Configure the channel data format - * @back: Backend device - * @chan: Channel number - * @data: Data format + * @back: Backend device + * @chan: Channel number + * @data: Data format * * Properly configure a channel with respect to the expected data format. A * @struct iio_backend_data_fmt must be passed with the settings. @@ -190,9 +190,9 @@ EXPORT_SYMBOL_NS_GPL(iio_backend_data_format_set, IIO_BACKEND); /** * iio_backend_data_source_set - Select data source - * @back: Backend device - * @chan: Channel number - * @data: Data source + * @back: Backend device + * @chan: Channel number + * @data: Data source * * A given backend may have different sources to stream/sync data. This allows * to choose that source. @@ -212,9 +212,9 @@ EXPORT_SYMBOL_NS_GPL(iio_backend_data_source_set, IIO_BACKEND); /** * iio_backend_set_sampling_freq - Set channel sampling rate - * @back: Backend device - * @chan: Channel number - * @sample_rate_hz: Sample rate + * @back: Backend device + * @chan: Channel number + * @sample_rate_hz: Sample rate * * RETURNS: * 0 on success, negative error number on failure. @@ -226,6 +226,92 @@ int iio_backend_set_sampling_freq(struct iio_backend *back, unsigned int chan, } EXPORT_SYMBOL_NS_GPL(iio_backend_set_sampling_freq, IIO_BACKEND); +/** + * iio_backend_test_pattern_set - Configure a test pattern + * @back: Backend device + * @chan: Channel number + * @pattern: Test pattern + * + * Configure a test pattern on the backend. This is typically used for + * calibrating the timings on the data digital interface. + * + * RETURNS: + * 0 on success, negative error number on failure. + */ +int iio_backend_test_pattern_set(struct iio_backend *back, + unsigned int chan, + enum iio_backend_test_pattern pattern) +{ + if (pattern >= IIO_BACKEND_TEST_PATTERN_MAX) + return -EINVAL; + + return iio_backend_op_call(back, test_pattern_set, chan, pattern); +} +EXPORT_SYMBOL_NS_GPL(iio_backend_test_pattern_set, IIO_BACKEND); + +/** + * iio_backend_chan_status - Get the channel status + * @back: Backend device + * @chan: Channel number + * @error: Error indication + * + * Get the current state of the backend channel. Typically used to check if + * there were any errors sending/receiving data. + * + * RETURNS: + * 0 on success, negative error number on failure. + */ +int iio_backend_chan_status(struct iio_backend *back, unsigned int chan, + bool *error) +{ + return iio_backend_op_call(back, chan_status, chan, error); +} +EXPORT_SYMBOL_NS_GPL(iio_backend_chan_status, IIO_BACKEND); + +/** + * iio_backend_iodelay_set - Set digital I/O delay + * @back: Backend device + * @lane: Lane number + * @taps: Number of taps + * + * Controls delays on sending/receiving data. One usecase for this is to + * calibrate the data digital interface so we get the best results when + * transferring data. Note that @taps has no unit since the actual delay per tap + * is very backend specific. Hence, frontend devices typically should go through + * an array of @taps (the size of that array should typically match the size of + * calibration points on the frontend device) and call this API. + * + * RETURNS: + * 0 on success, negative error number on failure. + */ +int iio_backend_iodelay_set(struct iio_backend *back, unsigned int lane, + unsigned int taps) +{ + return iio_backend_op_call(back, iodelay_set, lane, taps); +} +EXPORT_SYMBOL_NS_GPL(iio_backend_iodelay_set, IIO_BACKEND); + +/** + * iio_backend_data_sample_trigger - Control when to sample data + * @back: Backend device + * @trigger: Data trigger + * + * Mostly useful for input backends. Configures the backend for when to sample + * data (eg: rising vs falling edge). + * + * RETURNS: + * 0 on success, negative error number on failure. + */ +int iio_backend_data_sample_trigger(struct iio_backend *back, + enum iio_backend_sample_trigger trigger) +{ + if (trigger >= IIO_BACKEND_SAMPLE_TRIGGER_MAX) + return -EINVAL; + + return iio_backend_op_call(back, data_sample_trigger, trigger); +} +EXPORT_SYMBOL_NS_GPL(iio_backend_data_sample_trigger, IIO_BACKEND); + static void iio_backend_free_buffer(void *arg) { struct iio_backend_buffer_pair *pair = arg; @@ -235,9 +321,9 @@ static void iio_backend_free_buffer(void *arg) /** * devm_iio_backend_request_buffer - Device managed buffer request - * @dev: Consumer device for the backend - * @back: Backend device - * @indio_dev: IIO device + * @dev: Consumer device for the backend + * @back: Backend device + * @indio_dev: IIO device * * Request an IIO buffer from the backend. The type of the buffer (typically * INDIO_BUFFER_HARDWARE) is up to the backend to decide. This is because, @@ -300,10 +386,10 @@ static struct iio_backend *iio_backend_from_indio_dev_parent(const struct device /** * iio_backend_ext_info_get - IIO ext_info read callback - * @indio_dev: IIO device - * @private: Data private to the driver - * @chan: IIO channel - * @buf: Buffer where to place the attribute data + * @indio_dev: IIO device + * @private: Data private to the driver + * @chan: IIO channel + * @buf: Buffer where to place the attribute data * * This helper is intended to be used by backends that extend an IIO channel * (through iio_backend_extend_chan_spec()) with extended info. In that case, @@ -335,11 +421,11 @@ EXPORT_SYMBOL_NS_GPL(iio_backend_ext_info_get, IIO_BACKEND); /** * iio_backend_ext_info_set - IIO ext_info write callback - * @indio_dev: IIO device - * @private: Data private to the driver - * @chan: IIO channel - * @buf: Buffer holding the sysfs attribute - * @len: Buffer length + * @indio_dev: IIO device + * @private: Data private to the driver + * @chan: IIO channel + * @buf: Buffer holding the sysfs attribute + * @len: Buffer length * * This helper is intended to be used by backends that extend an IIO channel * (trough iio_backend_extend_chan_spec()) with extended info. In that case, @@ -365,9 +451,9 @@ EXPORT_SYMBOL_NS_GPL(iio_backend_ext_info_set, IIO_BACKEND); /** * iio_backend_extend_chan_spec - Extend an IIO channel - * @indio_dev: IIO device - * @back: Backend device - * @chan: IIO channel + * @indio_dev: IIO device + * @back: Backend device + * @chan: IIO channel * * Some backends may have their own functionalities and hence capable of * extending a frontend's channel. @@ -449,8 +535,8 @@ static int __devm_iio_backend_get(struct device *dev, struct iio_backend *back) /** * devm_iio_backend_get - Device managed backend device get - * @dev: Consumer device for the backend - * @name: Backend name + * @dev: Consumer device for the backend + * @name: Backend name * * Get's the backend associated with @dev. * @@ -501,8 +587,8 @@ EXPORT_SYMBOL_NS_GPL(devm_iio_backend_get, IIO_BACKEND); /** * __devm_iio_backend_get_from_fwnode_lookup - Device managed fwnode backend device get - * @dev: Consumer device for the backend - * @fwnode: Firmware node of the backend device + * @dev: Consumer device for the backend + * @fwnode: Firmware node of the backend device * * Search the backend list for a device matching @fwnode. * This API should not be used and it's only present for preventing the first @@ -536,7 +622,7 @@ EXPORT_SYMBOL_NS_GPL(__devm_iio_backend_get_from_fwnode_lookup, IIO_BACKEND); /** * iio_backend_get_priv - Get driver private data - * @back: Backend device + * @back: Backend device */ void *iio_backend_get_priv(const struct iio_backend *back) { @@ -554,9 +640,9 @@ static void iio_backend_unregister(void *arg) /** * devm_iio_backend_register - Device managed backend device register - * @dev: Backend device being registered - * @ops: Backend ops - * @priv: Device private data + * @dev: Backend device being registered + * @ops: Backend ops + * @priv: Device private data * * @ops is mandatory. Not providing it results in -EINVAL. * diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c index 421e059d1f190a..dcc87a9015e8be 100644 --- a/drivers/iio/pressure/zpa2326.c +++ b/drivers/iio/pressure/zpa2326.c @@ -861,13 +861,13 @@ static int zpa2326_wait_oneshot_completion(const struct iio_dev *indio_dev, struct zpa2326_private *private) { unsigned int val; - long timeout; + long time_left; zpa2326_dbg(indio_dev, "waiting for one shot completion interrupt"); - timeout = wait_for_completion_interruptible_timeout( + time_left = wait_for_completion_interruptible_timeout( &private->data_ready, ZPA2326_CONVERSION_JIFFIES); - if (timeout > 0) + if (time_left > 0) /* * Interrupt handler completed before timeout: return operation * status. @@ -877,10 +877,10 @@ static int zpa2326_wait_oneshot_completion(const struct iio_dev *indio_dev, /* Clear all interrupts just to be sure. */ regmap_read(private->regmap, ZPA2326_INT_SOURCE_REG, &val); - if (!timeout) { + if (!time_left) { /* Timed out. */ zpa2326_warn(indio_dev, "no one shot interrupt occurred (%ld)", - timeout); + time_left); return -ETIME; } diff --git a/drivers/iio/temperature/mcp9600.c b/drivers/iio/temperature/mcp9600.c index 46845804292bf0..7a3eef5d5e752a 100644 --- a/drivers/iio/temperature/mcp9600.c +++ b/drivers/iio/temperature/mcp9600.c @@ -52,7 +52,8 @@ static int mcp9600_read(struct mcp9600_data *data, if (ret < 0) return ret; - *val = ret; + + *val = sign_extend32(ret, 15); return 0; } diff --git a/include/linux/iio/backend.h b/include/linux/iio/backend.h index 9d144631134db0..8099759d724280 100644 --- a/include/linux/iio/backend.h +++ b/include/linux/iio/backend.h @@ -24,9 +24,9 @@ enum iio_backend_data_source { /** * IIO_BACKEND_EX_INFO - Helper for an IIO extended channel attribute - * @_name: Attribute name - * @_shared: Whether the attribute is shared between all channels - * @_what: Data private to the driver + * @_name: Attribute name + * @_shared: Whether the attribute is shared between all channels + * @_what: Data private to the driver */ #define IIO_BACKEND_EX_INFO(_name, _shared, _what) { \ .name = (_name), \ @@ -38,10 +38,10 @@ enum iio_backend_data_source { /** * struct iio_backend_data_fmt - Backend data format - * @type: Data type. - * @sign_extend: Bool to tell if the data is sign extended. - * @enable: Enable/Disable the data format module. If disabled, - * not formatting will happen. + * @type: Data type. + * @sign_extend: Bool to tell if the data is sign extended. + * @enable: Enable/Disable the data format module. If disabled, + * not formatting will happen. */ struct iio_backend_data_fmt { enum iio_backend_data_type type; @@ -49,20 +49,38 @@ struct iio_backend_data_fmt { bool enable; }; +/* vendor specific from 32 */ +enum iio_backend_test_pattern { + IIO_BACKEND_NO_TEST_PATTERN, + /* modified prbs9 */ + IIO_BACKEND_ADI_PRBS_9A = 32, + IIO_BACKEND_TEST_PATTERN_MAX +}; + +enum iio_backend_sample_trigger { + IIO_BACKEND_SAMPLE_TRIGGER_EDGE_FALLING, + IIO_BACKEND_SAMPLE_TRIGGER_EDGE_RISING, + IIO_BACKEND_SAMPLE_TRIGGER_MAX +}; + /** * struct iio_backend_ops - operations structure for an iio_backend - * @enable: Enable backend. - * @disable: Disable backend. - * @chan_enable: Enable one channel. - * @chan_disable: Disable one channel. - * @data_format_set: Configure the data format for a specific channel. - * @data_source_set: Configure the data source for a specific channel. - * @set_sample_rate: Configure the sampling rate for a specific channel. - * @request_buffer: Request an IIO buffer. - * @free_buffer: Free an IIO buffer. - * @extend_chan_spec: Extend an IIO channel. - * @ext_info_set: Extended info setter. - * @ext_info_get: Extended info getter. + * @enable: Enable backend. + * @disable: Disable backend. + * @chan_enable: Enable one channel. + * @chan_disable: Disable one channel. + * @data_format_set: Configure the data format for a specific channel. + * @data_source_set: Configure the data source for a specific channel. + * @set_sample_rate: Configure the sampling rate for a specific channel. + * @test_pattern_set: Configure a test pattern. + * @chan_status: Get the channel status. + * @iodelay_set: Set digital I/O delay. + * @data_sample_trigger: Control when to sample data. + * @request_buffer: Request an IIO buffer. + * @free_buffer: Free an IIO buffer. + * @extend_chan_spec: Extend an IIO channel. + * @ext_info_set: Extended info setter. + * @ext_info_get: Extended info getter. **/ struct iio_backend_ops { int (*enable)(struct iio_backend *back); @@ -75,6 +93,15 @@ struct iio_backend_ops { enum iio_backend_data_source data); int (*set_sample_rate)(struct iio_backend *back, unsigned int chan, u64 sample_rate_hz); + int (*test_pattern_set)(struct iio_backend *back, + unsigned int chan, + enum iio_backend_test_pattern pattern); + int (*chan_status)(struct iio_backend *back, unsigned int chan, + bool *error); + int (*iodelay_set)(struct iio_backend *back, unsigned int chan, + unsigned int taps); + int (*data_sample_trigger)(struct iio_backend *back, + enum iio_backend_sample_trigger trigger); struct iio_buffer *(*request_buffer)(struct iio_backend *back, struct iio_dev *indio_dev); void (*free_buffer)(struct iio_backend *back, @@ -97,6 +124,15 @@ int iio_backend_data_source_set(struct iio_backend *back, unsigned int chan, enum iio_backend_data_source data); int iio_backend_set_sampling_freq(struct iio_backend *back, unsigned int chan, u64 sample_rate_hz); +int iio_backend_test_pattern_set(struct iio_backend *back, + unsigned int chan, + enum iio_backend_test_pattern pattern); +int iio_backend_chan_status(struct iio_backend *back, unsigned int chan, + bool *error); +int iio_backend_iodelay_set(struct iio_backend *back, unsigned int lane, + unsigned int taps); +int iio_backend_data_sample_trigger(struct iio_backend *back, + enum iio_backend_sample_trigger trigger); int devm_iio_backend_request_buffer(struct device *dev, struct iio_backend *back, struct iio_dev *indio_dev); diff --git a/include/linux/iio/common/inv_sensors_timestamp.h b/include/linux/iio/common/inv_sensors_timestamp.h index a47d304d1ba7c4..8d506f1e9df292 100644 --- a/include/linux/iio/common/inv_sensors_timestamp.h +++ b/include/linux/iio/common/inv_sensors_timestamp.h @@ -71,8 +71,7 @@ int inv_sensors_timestamp_update_odr(struct inv_sensors_timestamp *ts, uint32_t period, bool fifo); void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts, - uint32_t fifo_period, size_t fifo_nb, - size_t sensor_nb, int64_t timestamp); + size_t sample_nb, int64_t timestamp); static inline int64_t inv_sensors_timestamp_pop(struct inv_sensors_timestamp *ts) { |