From a9ab624edd9186fbad734cfe5d606a6da3ca34db Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 7 Jan 2020 13:45:32 +0200 Subject: [PATCH 01/29] iio: adc: stm32-dfsdm: Use dma_request_chan() instead dma_request_slave_channel() dma_request_slave_channel() is a wrapper on top of dma_request_chan() eating up the error code. By using dma_request_chan() directly the driver can support deferred probing against DMA. Signed-off-by: Peter Ujfalusi Acked-by: Olivier Moysan Acked-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-dfsdm-adc.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index e493242c266e..74a2211bdff4 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -1383,9 +1383,13 @@ static int stm32_dfsdm_dma_request(struct iio_dev *indio_dev) { struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); - adc->dma_chan = dma_request_slave_channel(&indio_dev->dev, "rx"); - if (!adc->dma_chan) - return -EINVAL; + adc->dma_chan = dma_request_chan(&indio_dev->dev, "rx"); + if (IS_ERR(adc->dma_chan)) { + int ret = PTR_ERR(adc->dma_chan); + + adc->dma_chan = NULL; + return ret; + } adc->rx_buf = dma_alloc_coherent(adc->dma_chan->device->dev, DFSDM_DMA_BUFFER_SIZE, @@ -1509,7 +1513,16 @@ static int stm32_dfsdm_adc_init(struct iio_dev *indio_dev) init_completion(&adc->completion); /* Optionally request DMA */ - if (stm32_dfsdm_dma_request(indio_dev)) { + ret = stm32_dfsdm_dma_request(indio_dev); + if (ret) { + if (ret != -ENODEV) { + if (ret != -EPROBE_DEFER) + dev_err(&indio_dev->dev, + "DMA channel request failed with %d\n", + ret); + return ret; + } + dev_dbg(&indio_dev->dev, "No DMA support\n"); return 0; } From 735404b846dffcb320264f62b76e6f70012214dd Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 8 Jan 2020 10:08:01 +0200 Subject: [PATCH 02/29] iio: adc: stm32-adc: Use dma_request_chan() instead dma_request_slave_channel() dma_request_slave_channel() is a wrapper on top of dma_request_chan() eating up the error code. By using dma_request_chan() directly the driver can support deferred probing against DMA. Signed-off-by: Peter Ujfalusi Acked-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-adc.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 5f05bf9f16ea..80c3f963527b 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -1796,9 +1796,21 @@ static int stm32_adc_dma_request(struct iio_dev *indio_dev) struct dma_slave_config config; int ret; - adc->dma_chan = dma_request_slave_channel(&indio_dev->dev, "rx"); - if (!adc->dma_chan) + adc->dma_chan = dma_request_chan(&indio_dev->dev, "rx"); + if (IS_ERR(adc->dma_chan)) { + ret = PTR_ERR(adc->dma_chan); + if (ret != -ENODEV) { + if (ret != -EPROBE_DEFER) + dev_err(&indio_dev->dev, + "DMA channel request failed with %d\n", + ret); + return ret; + } + + /* DMA is optional: fall back to IRQ mode */ + adc->dma_chan = NULL; return 0; + } adc->rx_buf = dma_alloc_coherent(adc->dma_chan->device->dev, STM32_DMA_BUFFER_SIZE, From 687d39d4512aa5f644450d0662f40aeeac1e84a7 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 7 Jan 2020 13:37:29 +0200 Subject: [PATCH 03/29] iio: adc: at91-sama5d2_adc: Use dma_request_chan() instead dma_request_slave_channel() dma_request_slave_channel() is a wrapper on top of dma_request_chan() eating up the error code. The dma_request_chan() is the standard API to request slave channel, clients should be moved away from the legacy API to allow us to retire them. Signed-off-by: Peter Ujfalusi Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91-sama5d2_adc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index e1850f3d5cf3..a5c7771227d5 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -1444,10 +1444,10 @@ static void at91_adc_dma_init(struct platform_device *pdev) if (st->dma_st.dma_chan) return; - st->dma_st.dma_chan = dma_request_slave_channel(&pdev->dev, "rx"); - - if (!st->dma_st.dma_chan) { + st->dma_st.dma_chan = dma_request_chan(&pdev->dev, "rx"); + if (IS_ERR(st->dma_st.dma_chan)) { dev_info(&pdev->dev, "can't get DMA channel\n"); + st->dma_st.dma_chan = NULL; goto dma_exit; } From 380b107bbf9449ddea0637cefe65a6cbf7b6ca84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Tue, 7 Jan 2020 13:17:04 +0200 Subject: [PATCH 04/29] iio: adis: Introduce timeouts structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The adis library only allows to define a `startup_delay` which for some devices is enough. However, other devices define different timeouts with significantly different timings which could lead to devices to not wait enough time or to wait a lot more than necessary (which is not efficient). This patch introduces a new timeout struct that must be passed into `adis_init()`. There are mainly, for now, three timeouts used. This is also an introductory patch with the goal of refactoring `adis_initial_startup()`. New driver's (eg: adis16480, adis16460) are replicating code for the device initial setup. With some changes (being this the first one) we can pass this to `adis_initial_startup()`. Signed-off-by: Nuno Sá Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/accel/adis16201.c | 7 +++ drivers/iio/accel/adis16209.c | 7 +++ drivers/iio/gyro/adis16136.c | 40 ++++++++++++++++- drivers/iio/gyro/adis16260.c | 7 +++ drivers/iio/imu/adis.c | 18 ++++++-- drivers/iio/imu/adis16400.c | 63 ++++++++++++++++++++++++++- drivers/iio/imu/adis16460.c | 7 +++ drivers/iio/imu/adis16480.c | 58 +++++++++++++++++++++++- drivers/staging/iio/accel/adis16203.c | 7 +++ drivers/staging/iio/accel/adis16240.c | 7 +++ include/linux/iio/imu/adis.h | 13 ++++++ 11 files changed, 227 insertions(+), 7 deletions(-) diff --git a/drivers/iio/accel/adis16201.c b/drivers/iio/accel/adis16201.c index c4810c73b2a2..c92d22387b01 100644 --- a/drivers/iio/accel/adis16201.c +++ b/drivers/iio/accel/adis16201.c @@ -233,6 +233,12 @@ static const char * const adis16201_status_error_msgs[] = { [ADIS16201_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.975V", }; +static const struct adis_timeout adis16201_timeouts = { + .reset_ms = ADIS16201_STARTUP_DELAY_MS, + .sw_reset_ms = ADIS16201_STARTUP_DELAY_MS, + .self_test_ms = ADIS16201_STARTUP_DELAY_MS, +}; + static const struct adis_data adis16201_data = { .read_delay = 20, .msc_ctrl_reg = ADIS16201_MSC_CTRL_REG, @@ -242,6 +248,7 @@ static const struct adis_data adis16201_data = { .self_test_mask = ADIS16201_MSC_CTRL_SELF_TEST_EN, .self_test_no_autoclear = true, .startup_delay = ADIS16201_STARTUP_DELAY_MS, + .timeouts = &adis16201_timeouts, .status_error_msgs = adis16201_status_error_msgs, .status_error_mask = BIT(ADIS16201_DIAG_STAT_SPI_FAIL_BIT) | diff --git a/drivers/iio/accel/adis16209.c b/drivers/iio/accel/adis16209.c index 98d77af8a2b0..f5a78fc11919 100644 --- a/drivers/iio/accel/adis16209.c +++ b/drivers/iio/accel/adis16209.c @@ -243,6 +243,12 @@ static const char * const adis16209_status_error_msgs[] = { [ADIS16209_STAT_POWER_LOW_BIT] = "Power supply below 2.975V", }; +static const struct adis_timeout adis16209_timeouts = { + .reset_ms = ADIS16209_STARTUP_DELAY_MS, + .self_test_ms = ADIS16209_STARTUP_DELAY_MS, + .sw_reset_ms = ADIS16209_STARTUP_DELAY_MS, +}; + static const struct adis_data adis16209_data = { .read_delay = 30, .msc_ctrl_reg = ADIS16209_MSC_CTRL_REG, @@ -252,6 +258,7 @@ static const struct adis_data adis16209_data = { .self_test_mask = ADIS16209_MSC_CTRL_SELF_TEST_EN, .self_test_no_autoclear = true, .startup_delay = ADIS16209_STARTUP_DELAY_MS, + .timeouts = &adis16209_timeouts, .status_error_msgs = adis16209_status_error_msgs, .status_error_mask = BIT(ADIS16209_STAT_SELFTEST_FAIL_BIT) | diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c index f10c4f173898..dc91d8df7697 100644 --- a/drivers/iio/gyro/adis16136.c +++ b/drivers/iio/gyro/adis16136.c @@ -59,6 +59,7 @@ struct adis16136_chip_info { unsigned int precision; unsigned int fullscale; + const struct adis_timeout *timeouts; }; struct adis16136 { @@ -490,30 +491,63 @@ enum adis16136_id { ID_ADIS16137, }; +static const struct adis_timeout adis16133_timeouts = { + .reset_ms = 75, + .sw_reset_ms = 75, + .self_test_ms = 50, +}; + +static const struct adis_timeout adis16136_timeouts = { + .reset_ms = 128, + .sw_reset_ms = 75, + .self_test_ms = 245, +}; + static const struct adis16136_chip_info adis16136_chip_info[] = { [ID_ADIS16133] = { .precision = IIO_DEGREE_TO_RAD(1200), .fullscale = 24000, + .timeouts = &adis16133_timeouts, }, [ID_ADIS16135] = { .precision = IIO_DEGREE_TO_RAD(300), .fullscale = 24000, + .timeouts = &adis16133_timeouts, }, [ID_ADIS16136] = { .precision = IIO_DEGREE_TO_RAD(450), .fullscale = 24623, + .timeouts = &adis16136_timeouts, }, [ID_ADIS16137] = { .precision = IIO_DEGREE_TO_RAD(1000), .fullscale = 24609, + .timeouts = &adis16136_timeouts, }, }; +static struct adis_data *adis16136_adis_data_alloc(struct adis16136 *st, + struct device *dev) +{ + struct adis_data *data; + + data = devm_kmalloc(dev, sizeof(struct adis_data), GFP_KERNEL); + if (!data) + return ERR_PTR(-ENOMEM); + + memcpy(data, &adis16136_data, sizeof(*data)); + + data->timeouts = st->chip_info->timeouts; + + return data; +} + static int adis16136_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); struct adis16136 *adis16136; struct iio_dev *indio_dev; + const struct adis_data *adis16136_data; int ret; indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adis16136)); @@ -532,7 +566,11 @@ static int adis16136_probe(struct spi_device *spi) indio_dev->info = &adis16136_info; indio_dev->modes = INDIO_DIRECT_MODE; - ret = adis_init(&adis16136->adis, indio_dev, spi, &adis16136_data); + adis16136_data = adis16136_adis_data_alloc(adis16136, &spi->dev); + if (IS_ERR(adis16136_data)) + return PTR_ERR(adis16136_data); + + ret = adis_init(&adis16136->adis, indio_dev, spi, adis16136_data); if (ret) return ret; diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c index 726a0aa321a8..0e3a66a7726d 100644 --- a/drivers/iio/gyro/adis16260.c +++ b/drivers/iio/gyro/adis16260.c @@ -332,6 +332,12 @@ static const char * const adis1620_status_error_msgs[] = { [ADIS16260_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 4.75", }; +static const struct adis_timeout adis16260_timeouts = { + .reset_ms = ADIS16260_STARTUP_DELAY, + .sw_reset_ms = ADIS16260_STARTUP_DELAY, + .self_test_ms = ADIS16260_STARTUP_DELAY, +}; + static const struct adis_data adis16260_data = { .write_delay = 30, .read_delay = 30, @@ -341,6 +347,7 @@ static const struct adis_data adis16260_data = { .self_test_mask = ADIS16260_MSC_CTRL_MEM_TEST, .startup_delay = ADIS16260_STARTUP_DELAY, + .timeouts = &adis16260_timeouts, .status_error_msgs = adis1620_status_error_msgs, .status_error_mask = BIT(ADIS16260_DIAG_STAT_FLASH_CHK_BIT) | diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 9ba4a7c8e7ad..8f0867495ef5 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -317,19 +317,25 @@ EXPORT_SYMBOL_GPL(__adis_check_status); int __adis_reset(struct adis *adis) { int ret; + const struct adis_timeout *timeouts = adis->data->timeouts; ret = __adis_write_reg_8(adis, adis->data->glob_cmd_reg, ADIS_GLOB_CMD_SW_RESET); - if (ret) + if (ret) { dev_err(&adis->spi->dev, "Failed to reset device: %d\n", ret); + return ret; + } - return ret; + msleep(timeouts->sw_reset_ms); + + return 0; } EXPORT_SYMBOL_GPL(__adis_reset); static int adis_self_test(struct adis *adis) { int ret; + const struct adis_timeout *timeouts = adis->data->timeouts; ret = __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, adis->data->self_test_mask); @@ -339,7 +345,7 @@ static int adis_self_test(struct adis *adis) return ret; } - msleep(adis->data->startup_delay); + msleep(timeouts->self_test_ms); ret = __adis_check_status(adis); @@ -368,7 +374,6 @@ int adis_initial_startup(struct adis *adis) if (ret) { dev_err(&adis->spi->dev, "Self-test failed, trying reset.\n"); __adis_reset(adis); - msleep(adis->data->startup_delay); ret = adis_self_test(adis); if (ret) { dev_err(&adis->spi->dev, "Second self-test failed, giving up.\n"); @@ -444,6 +449,11 @@ EXPORT_SYMBOL_GPL(adis_single_conversion); int adis_init(struct adis *adis, struct iio_dev *indio_dev, struct spi_device *spi, const struct adis_data *data) { + if (!data || !data->timeouts) { + dev_err(&spi->dev, "No config data or timeouts not defined!\n"); + return -EINVAL; + } + mutex_init(&adis->state_lock); adis->spi = spi; adis->data = data; diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c index 662cb5367c11..51b1ec23b8ef 100644 --- a/drivers/iio/imu/adis16400.c +++ b/drivers/iio/imu/adis16400.c @@ -156,6 +156,7 @@ struct adis16400_state; struct adis16400_chip_info { const struct iio_chan_spec *channels; + const struct adis_timeout *timeouts; const int num_channels; const long flags; unsigned int gyro_scale_micro; @@ -929,6 +930,36 @@ static const struct iio_chan_spec adis16334_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP), }; +static const struct adis_timeout adis16300_timeouts = { + .reset_ms = ADIS16400_STARTUP_DELAY, + .sw_reset_ms = ADIS16400_STARTUP_DELAY, + .self_test_ms = ADIS16400_STARTUP_DELAY, +}; + +static const struct adis_timeout adis16362_timeouts = { + .reset_ms = 130, + .sw_reset_ms = 130, + .self_test_ms = 12, +}; + +static const struct adis_timeout adis16400_timeouts = { + .reset_ms = 170, + .sw_reset_ms = 170, + .self_test_ms = 12, +}; + +static const struct adis_timeout adis16445_timeouts = { + .reset_ms = 55, + .sw_reset_ms = 55, + .self_test_ms = 16, +}; + +static const struct adis_timeout adis16448_timeouts = { + .reset_ms = 90, + .sw_reset_ms = 90, + .self_test_ms = 45, +}; + static struct adis16400_chip_info adis16400_chips[] = { [ADIS16300] = { .channels = adis16300_channels, @@ -941,6 +972,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, + .timeouts = &adis16300_timeouts, }, [ADIS16334] = { .channels = adis16334_channels, @@ -964,6 +996,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .flags = ADIS16400_NO_BURST | ADIS16400_HAS_SLOW_MODE, .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, + .timeouts = &adis16300_timeouts, }, [ADIS16360] = { .channels = adis16350_channels, @@ -976,6 +1009,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, + .timeouts = &adis16300_timeouts, }, [ADIS16362] = { .channels = adis16350_channels, @@ -988,6 +1022,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, + .timeouts = &adis16362_timeouts, }, [ADIS16364] = { .channels = adis16350_channels, @@ -1000,6 +1035,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, + .timeouts = &adis16362_timeouts, }, [ADIS16367] = { .channels = adis16350_channels, @@ -1012,6 +1048,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, + .timeouts = &adis16300_timeouts, }, [ADIS16400] = { .channels = adis16400_channels, @@ -1023,6 +1060,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, + .timeouts = &adis16400_timeouts, }, [ADIS16445] = { .channels = adis16445_channels, @@ -1036,6 +1074,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */ .set_freq = adis16334_set_freq, .get_freq = adis16334_get_freq, + .timeouts = &adis16445_timeouts, }, [ADIS16448] = { .channels = adis16448_channels, @@ -1049,6 +1088,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */ .set_freq = adis16334_set_freq, .get_freq = adis16334_get_freq, + .timeouts = &adis16448_timeouts, } }; @@ -1120,11 +1160,28 @@ static void adis16400_setup_chan_mask(struct adis16400_state *st) } } +static struct adis_data *adis16400_adis_data_alloc(struct adis16400_state *st, + struct device *dev) +{ + struct adis_data *data; + + data = devm_kmalloc(dev, sizeof(struct adis_data), GFP_KERNEL); + if (!data) + return ERR_PTR(-ENOMEM); + + memcpy(data, &adis16400_data, sizeof(*data)); + + data->timeouts = st->variant->timeouts; + + return data; +} + static int adis16400_probe(struct spi_device *spi) { struct adis16400_state *st; struct iio_dev *indio_dev; int ret; + const struct adis_data *adis16400_data; indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (indio_dev == NULL) @@ -1151,7 +1208,11 @@ static int adis16400_probe(struct spi_device *spi) st->adis.burst->extra_len = sizeof(u16); } - ret = adis_init(&st->adis, indio_dev, spi, &adis16400_data); + adis16400_data = adis16400_adis_data_alloc(st, &spi->dev); + if (IS_ERR(adis16400_data)) + return PTR_ERR(adis16400_data); + + ret = adis_init(&st->adis, indio_dev, spi, adis16400_data); if (ret) return ret; diff --git a/drivers/iio/imu/adis16460.c b/drivers/iio/imu/adis16460.c index b55812521537..9539cfe4a259 100644 --- a/drivers/iio/imu/adis16460.c +++ b/drivers/iio/imu/adis16460.c @@ -383,6 +383,12 @@ static const char * const adis16460_status_error_msgs[] = { [ADIS16460_DIAG_STAT_FLASH_UPT] = "Flash update failure", }; +static const struct adis_timeout adis16460_timeouts = { + .reset_ms = 225, + .sw_reset_ms = 225, + .self_test_ms = 10, +}; + static const struct adis_data adis16460_data = { .diag_stat_reg = ADIS16460_REG_DIAG_STAT, .glob_cmd_reg = ADIS16460_REG_GLOB_CMD, @@ -398,6 +404,7 @@ static const struct adis_data adis16460_data = { BIT(ADIS16460_DIAG_STAT_SPI_COMM) | BIT(ADIS16460_DIAG_STAT_FLASH_UPT), .enable_irq = adis16460_enable_irq, + .timeouts = &adis16460_timeouts, }; static int adis16460_probe(struct spi_device *spi) diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c index f73094e8d35d..f0ad7ce64861 100644 --- a/drivers/iio/imu/adis16480.c +++ b/drivers/iio/imu/adis16480.c @@ -138,6 +138,7 @@ struct adis16480_chip_info { unsigned int max_dec_rate; const unsigned int *filter_freqs; bool has_pps_clk_mode; + const struct adis_timeout *timeouts; }; enum adis16480_int_pin { @@ -794,6 +795,30 @@ enum adis16480_variant { ADIS16497_3, }; +static const struct adis_timeout adis16485_timeouts = { + .reset_ms = 560, + .sw_reset_ms = 120, + .self_test_ms = 12, +}; + +static const struct adis_timeout adis16480_timeouts = { + .reset_ms = 560, + .sw_reset_ms = 560, + .self_test_ms = 12, +}; + +static const struct adis_timeout adis16495_timeouts = { + .reset_ms = 170, + .sw_reset_ms = 130, + .self_test_ms = 40, +}; + +static const struct adis_timeout adis16495_1_timeouts = { + .reset_ms = 250, + .sw_reset_ms = 210, + .self_test_ms = 20, +}; + static const struct adis16480_chip_info adis16480_chip_info[] = { [ADIS16375] = { .channels = adis16485_channels, @@ -812,6 +837,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .int_clk = 2460000, .max_dec_rate = 2048, .filter_freqs = adis16480_def_filter_freqs, + .timeouts = &adis16485_timeouts, }, [ADIS16480] = { .channels = adis16480_channels, @@ -824,6 +850,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .int_clk = 2460000, .max_dec_rate = 2048, .filter_freqs = adis16480_def_filter_freqs, + .timeouts = &adis16480_timeouts, }, [ADIS16485] = { .channels = adis16485_channels, @@ -836,6 +863,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .int_clk = 2460000, .max_dec_rate = 2048, .filter_freqs = adis16480_def_filter_freqs, + .timeouts = &adis16485_timeouts, }, [ADIS16488] = { .channels = adis16480_channels, @@ -848,6 +876,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .int_clk = 2460000, .max_dec_rate = 2048, .filter_freqs = adis16480_def_filter_freqs, + .timeouts = &adis16485_timeouts, }, [ADIS16495_1] = { .channels = adis16485_channels, @@ -861,6 +890,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, + .timeouts = &adis16495_1_timeouts, }, [ADIS16495_2] = { .channels = adis16485_channels, @@ -874,6 +904,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, + .timeouts = &adis16495_1_timeouts, }, [ADIS16495_3] = { .channels = adis16485_channels, @@ -887,6 +918,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, + .timeouts = &adis16495_1_timeouts, }, [ADIS16497_1] = { .channels = adis16485_channels, @@ -900,6 +932,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, + .timeouts = &adis16495_1_timeouts, }, [ADIS16497_2] = { .channels = adis16485_channels, @@ -913,6 +946,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, + .timeouts = &adis16495_1_timeouts, }, [ADIS16497_3] = { .channels = adis16485_channels, @@ -926,6 +960,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, + .timeouts = &adis16495_1_timeouts, }, }; @@ -1195,9 +1230,26 @@ static int adis16480_get_ext_clocks(struct adis16480 *st) return 0; } +static struct adis_data *adis16480_adis_data_alloc(struct adis16480 *st, + struct device *dev) +{ + struct adis_data *data; + + data = devm_kmalloc(dev, sizeof(struct adis_data), GFP_KERNEL); + if (!data) + return ERR_PTR(-ENOMEM); + + memcpy(data, &adis16480_data, sizeof(*data)); + + data->timeouts = st->chip_info->timeouts; + + return data; +} + static int adis16480_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); + const struct adis_data *adis16480_data; struct iio_dev *indio_dev; struct adis16480 *st; int ret; @@ -1218,7 +1270,11 @@ static int adis16480_probe(struct spi_device *spi) indio_dev->info = &adis16480_info; indio_dev->modes = INDIO_DIRECT_MODE; - ret = adis_init(&st->adis, indio_dev, spi, &adis16480_data); + adis16480_data = adis16480_adis_data_alloc(st, &spi->dev); + if (IS_ERR(adis16480_data)) + return PTR_ERR(adis16480_data); + + ret = adis_init(&st->adis, indio_dev, spi, adis16480_data); if (ret) return ret; diff --git a/drivers/staging/iio/accel/adis16203.c b/drivers/staging/iio/accel/adis16203.c index 39687139a7d3..3d706ee02df0 100644 --- a/drivers/staging/iio/accel/adis16203.c +++ b/drivers/staging/iio/accel/adis16203.c @@ -237,6 +237,12 @@ static const char * const adis16203_status_error_msgs[] = { [ADIS16203_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.975V", }; +static const struct adis_timeout adis16203_timeouts = { + .reset_ms = ADIS16203_STARTUP_DELAY, + .sw_reset_ms = ADIS16203_STARTUP_DELAY, + .self_test_ms = ADIS16203_STARTUP_DELAY +}; + static const struct adis_data adis16203_data = { .read_delay = 20, .msc_ctrl_reg = ADIS16203_MSC_CTRL, @@ -246,6 +252,7 @@ static const struct adis_data adis16203_data = { .self_test_mask = ADIS16203_MSC_CTRL_SELF_TEST_EN, .self_test_no_autoclear = true, .startup_delay = ADIS16203_STARTUP_DELAY, + .timeouts = &adis16203_timeouts, .status_error_msgs = adis16203_status_error_msgs, .status_error_mask = BIT(ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT) | diff --git a/drivers/staging/iio/accel/adis16240.c b/drivers/staging/iio/accel/adis16240.c index 794f063e6c86..d4848ef78c75 100644 --- a/drivers/staging/iio/accel/adis16240.c +++ b/drivers/staging/iio/accel/adis16240.c @@ -359,6 +359,12 @@ static const char * const adis16240_status_error_msgs[] = { [ADIS16240_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.225V", }; +static const struct adis_timeout adis16240_timeouts = { + .reset_ms = ADIS16240_STARTUP_DELAY, + .sw_reset_ms = ADIS16240_STARTUP_DELAY, + .self_test_ms = ADIS16240_STARTUP_DELAY, +}; + static const struct adis_data adis16240_data = { .write_delay = 35, .read_delay = 35, @@ -369,6 +375,7 @@ static const struct adis_data adis16240_data = { .self_test_mask = ADIS16240_MSC_CTRL_SELF_TEST_EN, .self_test_no_autoclear = true, .startup_delay = ADIS16240_STARTUP_DELAY, + .timeouts = &adis16240_timeouts, .status_error_msgs = adis16240_status_error_msgs, .status_error_mask = BIT(ADIS16240_DIAG_STAT_PWRON_FAIL_BIT) | diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index 4b5bc0e06e69..853dc8c8365c 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -22,6 +22,17 @@ struct adis; struct adis_burst; +/** + * struct adis_timeouts - ADIS chip variant timeouts + * @reset_ms - Wait time after rst pin goes inactive + * @sw_reset_ms - Wait time after sw reset command + * @self_test_ms - Wait time after self test command + */ +struct adis_timeout { + u16 reset_ms; + u16 sw_reset_ms; + u16 self_test_ms; +}; /** * struct adis_data - ADIS chip variant specific data * @read_delay: SPI delay for read operations in us @@ -32,6 +43,7 @@ struct adis_burst; * @diag_stat_reg: Register address of the DIAG_STAT register * @status_error_msgs: Array of error messgaes * @status_error_mask: + * @timeouts: Chip specific delays */ struct adis_data { unsigned int read_delay; @@ -45,6 +57,7 @@ struct adis_data { unsigned int self_test_mask; bool self_test_no_autoclear; unsigned int startup_delay; + const struct adis_timeout *timeouts; const char * const *status_error_msgs; unsigned int status_error_mask; From 77038bd01ce66ae65bcb66266c9747b670b5facd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Tue, 7 Jan 2020 13:17:05 +0200 Subject: [PATCH 05/29] iio: adis: Remove startup_delay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All timeouts are now handled by a dedicated timeout struct. This variable is no longer needed. Signed-off-by: Nuno Sá Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/accel/adis16201.c | 1 - drivers/iio/accel/adis16209.c | 1 - drivers/iio/gyro/adis16136.c | 1 - drivers/iio/gyro/adis16260.c | 1 - drivers/iio/imu/adis16400.c | 1 - drivers/staging/iio/accel/adis16203.c | 1 - drivers/staging/iio/accel/adis16240.c | 1 - include/linux/iio/imu/adis.h | 1 - 8 files changed, 8 deletions(-) diff --git a/drivers/iio/accel/adis16201.c b/drivers/iio/accel/adis16201.c index c92d22387b01..0f0f27a8184e 100644 --- a/drivers/iio/accel/adis16201.c +++ b/drivers/iio/accel/adis16201.c @@ -247,7 +247,6 @@ static const struct adis_data adis16201_data = { .self_test_mask = ADIS16201_MSC_CTRL_SELF_TEST_EN, .self_test_no_autoclear = true, - .startup_delay = ADIS16201_STARTUP_DELAY_MS, .timeouts = &adis16201_timeouts, .status_error_msgs = adis16201_status_error_msgs, diff --git a/drivers/iio/accel/adis16209.c b/drivers/iio/accel/adis16209.c index f5a78fc11919..c6dbd2424e10 100644 --- a/drivers/iio/accel/adis16209.c +++ b/drivers/iio/accel/adis16209.c @@ -257,7 +257,6 @@ static const struct adis_data adis16209_data = { .self_test_mask = ADIS16209_MSC_CTRL_SELF_TEST_EN, .self_test_no_autoclear = true, - .startup_delay = ADIS16209_STARTUP_DELAY_MS, .timeouts = &adis16209_timeouts, .status_error_msgs = adis16209_status_error_msgs, diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c index dc91d8df7697..d5e03a406d4a 100644 --- a/drivers/iio/gyro/adis16136.c +++ b/drivers/iio/gyro/adis16136.c @@ -472,7 +472,6 @@ static const struct adis_data adis16136_data = { .msc_ctrl_reg = ADIS16136_REG_MSC_CTRL, .self_test_mask = ADIS16136_MSC_CTRL_SELF_TEST, - .startup_delay = 80, .read_delay = 10, .write_delay = 10, diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c index 0e3a66a7726d..be09b3e5910c 100644 --- a/drivers/iio/gyro/adis16260.c +++ b/drivers/iio/gyro/adis16260.c @@ -346,7 +346,6 @@ static const struct adis_data adis16260_data = { .diag_stat_reg = ADIS16260_DIAG_STAT, .self_test_mask = ADIS16260_MSC_CTRL_MEM_TEST, - .startup_delay = ADIS16260_STARTUP_DELAY, .timeouts = &adis16260_timeouts, .status_error_msgs = adis1620_status_error_msgs, diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c index 51b1ec23b8ef..cfb1c19eb930 100644 --- a/drivers/iio/imu/adis16400.c +++ b/drivers/iio/imu/adis16400.c @@ -1126,7 +1126,6 @@ static const struct adis_data adis16400_data = { .write_delay = 50, .self_test_mask = ADIS16400_MSC_CTRL_MEM_TEST, - .startup_delay = ADIS16400_STARTUP_DELAY, .status_error_msgs = adis16400_status_error_msgs, .status_error_mask = BIT(ADIS16400_DIAG_STAT_ZACCL_FAIL) | diff --git a/drivers/staging/iio/accel/adis16203.c b/drivers/staging/iio/accel/adis16203.c index 3d706ee02df0..39dfe3f7f254 100644 --- a/drivers/staging/iio/accel/adis16203.c +++ b/drivers/staging/iio/accel/adis16203.c @@ -251,7 +251,6 @@ static const struct adis_data adis16203_data = { .self_test_mask = ADIS16203_MSC_CTRL_SELF_TEST_EN, .self_test_no_autoclear = true, - .startup_delay = ADIS16203_STARTUP_DELAY, .timeouts = &adis16203_timeouts, .status_error_msgs = adis16203_status_error_msgs, diff --git a/drivers/staging/iio/accel/adis16240.c b/drivers/staging/iio/accel/adis16240.c index d4848ef78c75..39eb8364aa95 100644 --- a/drivers/staging/iio/accel/adis16240.c +++ b/drivers/staging/iio/accel/adis16240.c @@ -374,7 +374,6 @@ static const struct adis_data adis16240_data = { .self_test_mask = ADIS16240_MSC_CTRL_SELF_TEST_EN, .self_test_no_autoclear = true, - .startup_delay = ADIS16240_STARTUP_DELAY, .timeouts = &adis16240_timeouts, .status_error_msgs = adis16240_status_error_msgs, diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index 853dc8c8365c..d2fcf45b4cef 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -56,7 +56,6 @@ struct adis_data { unsigned int self_test_mask; bool self_test_no_autoclear; - unsigned int startup_delay; const struct adis_timeout *timeouts; const char * const *status_error_msgs; From f335fa7034d5444de53f22824afce52924d95253 Mon Sep 17 00:00:00 2001 From: Kent Gustavsson Date: Sat, 4 Jan 2020 19:19:29 +0100 Subject: [PATCH 06/29] iio: humidity: dht11 remove TODO since it doesn't make sense DHT11 isn't addressable and will trigger temperature measurement on any data sent on the bus. Signed-off-by: Kent Gustavsson Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/dht11.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iio/humidity/dht11.c b/drivers/iio/humidity/dht11.c index b459600e1a33..d05c6fdb758b 100644 --- a/drivers/iio/humidity/dht11.c +++ b/drivers/iio/humidity/dht11.c @@ -174,7 +174,6 @@ static irqreturn_t dht11_handle_irq(int irq, void *data) struct iio_dev *iio = data; struct dht11 *dht11 = iio_priv(iio); - /* TODO: Consider making the handler safe for IRQ sharing */ if (dht11->num_edges < DHT11_EDGES_PER_READ && dht11->num_edges >= 0) { dht11->edges[dht11->num_edges].ts = ktime_get_boottime_ns(); dht11->edges[dht11->num_edges++].value = From 4766897a9d3bd6af171cdc5ff140e8d132d62d40 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Fri, 3 Jan 2020 17:29:08 -0800 Subject: [PATCH 07/29] iio: chemical: atlas-sensor: add helper function atlas_buffer_num_channels() Add helper function to detect the number of channels to output in trigger handler. This is based on IIO_TIMESTAMP channel being the delimiter between input and output channels. Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/chemical/atlas-sensor.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/iio/chemical/atlas-sensor.c b/drivers/iio/chemical/atlas-sensor.c index 99095c80531b..2f0a6fed2589 100644 --- a/drivers/iio/chemical/atlas-sensor.c +++ b/drivers/iio/chemical/atlas-sensor.c @@ -86,6 +86,16 @@ static const struct regmap_config atlas_regmap_config = { .val_bits = 8, }; +static int atlas_buffer_num_channels(const struct iio_chan_spec *spec) +{ + int idx = 0; + + for (; spec->type != IIO_TIMESTAMP; spec++) + idx++; + + return idx; +}; + static const struct iio_chan_spec atlas_ph_channels[] = { { .type = IIO_PH, @@ -354,11 +364,12 @@ static irqreturn_t atlas_trigger_handler(int irq, void *private) struct iio_poll_func *pf = private; struct iio_dev *indio_dev = pf->indio_dev; struct atlas_data *data = iio_priv(indio_dev); + int channels = atlas_buffer_num_channels(data->chip->channels); int ret; ret = regmap_bulk_read(data->regmap, data->chip->data_reg, (u8 *) &data->buffer, - sizeof(__be32) * (data->chip->num_channels - 2)); + sizeof(__be32) * channels); if (!ret) iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, From a2dd9bd9334efb8dc0bdc0109abff3a7b57effb1 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 2 Jan 2020 09:36:29 +0100 Subject: [PATCH 08/29] iio: imu: st_lsm6dsx: check return value from st_lsm6dsx_sensor_set_enable Add missing return value check in st_lsm6dsx_read_oneshot disabling the sensor. The issue is reported by coverity with the following error: Unchecked return value: If the function returns an error value, the error value may be mistaken for a normal value. Addresses-Coverity-ID: 1446733 ("Unchecked return value") Fixes: b5969abfa8b8 ("iio: imu: st_lsm6dsx: add motion events") Fixes: 290a6ce11d93 ("iio: imu: add support to lsm6dsx driver") Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index d205b994a9e0..f3ad5694437a 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -1555,8 +1555,11 @@ static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor, if (err < 0) return err; - if (!hw->enable_event) - st_lsm6dsx_sensor_set_enable(sensor, false); + if (!hw->enable_event) { + err = st_lsm6dsx_sensor_set_enable(sensor, false); + if (err < 0) + return err; + } *val = (s16)le16_to_cpu(data); From e825070f697abddf3b9b0a675ed0ff1884114818 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 17 Dec 2019 19:10:38 +0200 Subject: [PATCH 09/29] iio: st_gyro: Correct data for LSM9DS0 gyro The commit 41c128cb25ce ("iio: st_gyro: Add lsm9ds0-gyro support") assumes that gyro in LSM9DS0 is the same as others with 0xd4 WAI ID, but datasheet tells slight different story, i.e. the first scale factor for the chip is 245 dps, and not 250 dps. Correct this by introducing a separate settings for LSM9DS0. Fixes: 41c128cb25ce ("iio: st_gyro: Add lsm9ds0-gyro support") Depends-on: 45a4e4220bf4 ("iio: gyro: st_gyro: fix L3GD20H support") Cc: Leonard Crestez Cc: Lorenzo Bianconi Cc: Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/st_gyro_core.c | 75 ++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index 57be68b291fa..26c50b24bc08 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c @@ -138,7 +138,6 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { [2] = LSM330DLC_GYRO_DEV_NAME, [3] = L3G4IS_GYRO_DEV_NAME, [4] = LSM330_GYRO_DEV_NAME, - [5] = LSM9DS0_GYRO_DEV_NAME, }, .ch = (struct iio_chan_spec *)st_gyro_16bit_channels, .odr = { @@ -208,6 +207,80 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { .multi_read_bit = true, .bootime = 2, }, + { + .wai = 0xd4, + .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, + .sensors_supported = { + [0] = LSM9DS0_GYRO_DEV_NAME, + }, + .ch = (struct iio_chan_spec *)st_gyro_16bit_channels, + .odr = { + .addr = 0x20, + .mask = GENMASK(7, 6), + .odr_avl = { + { .hz = 95, .value = 0x00, }, + { .hz = 190, .value = 0x01, }, + { .hz = 380, .value = 0x02, }, + { .hz = 760, .value = 0x03, }, + }, + }, + .pw = { + .addr = 0x20, + .mask = BIT(3), + .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE, + .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, + }, + .enable_axis = { + .addr = ST_SENSORS_DEFAULT_AXIS_ADDR, + .mask = ST_SENSORS_DEFAULT_AXIS_MASK, + }, + .fs = { + .addr = 0x23, + .mask = GENMASK(5, 4), + .fs_avl = { + [0] = { + .num = ST_GYRO_FS_AVL_245DPS, + .value = 0x00, + .gain = IIO_DEGREE_TO_RAD(8750), + }, + [1] = { + .num = ST_GYRO_FS_AVL_500DPS, + .value = 0x01, + .gain = IIO_DEGREE_TO_RAD(17500), + }, + [2] = { + .num = ST_GYRO_FS_AVL_2000DPS, + .value = 0x02, + .gain = IIO_DEGREE_TO_RAD(70000), + }, + }, + }, + .bdu = { + .addr = 0x23, + .mask = BIT(7), + }, + .drdy_irq = { + .int2 = { + .addr = 0x22, + .mask = BIT(3), + }, + /* + * The sensor has IHL (active low) and open + * drain settings, but only for INT1 and not + * for the DRDY line on INT2. + */ + .stat_drdy = { + .addr = ST_SENSORS_DEFAULT_STAT_ADDR, + .mask = GENMASK(2, 0), + }, + }, + .sim = { + .addr = 0x23, + .value = BIT(0), + }, + .multi_read_bit = true, + .bootime = 2, + }, { .wai = 0xd7, .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, From efc78983d21aeaf692006d42b92a006cdce3ed4d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 16 Dec 2019 19:38:52 +0200 Subject: [PATCH 10/29] iio: st_sensors: Drop redundant parameter from st_sensors_of_name_probe() Since we have access to the struct device_driver and thus to the ID table, there is no need to supply special parameters to st_sensors_of_name_probe(). Besides that we have a common API to get driver match data, there is no need to do matching separately for OF and ACPI. Taking into consideration above, simplify the ST sensors code. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_spi.c | 3 +- .../iio/common/st_sensors/st_sensors_core.c | 54 +++++++++---------- .../iio/common/st_sensors/st_sensors_i2c.c | 21 -------- drivers/iio/gyro/st_gyro_i2c.c | 3 +- drivers/iio/gyro/st_gyro_spi.c | 3 +- drivers/iio/magnetometer/st_magn_i2c.c | 3 +- drivers/iio/magnetometer/st_magn_spi.c | 3 +- drivers/iio/pressure/st_pressure_i2c.c | 14 +---- drivers/iio/pressure/st_pressure_spi.c | 3 +- include/linux/iio/common/st_sensors.h | 12 +---- include/linux/iio/common/st_sensors_i2c.h | 10 ---- 11 files changed, 33 insertions(+), 96 deletions(-) diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c index 8af7027d5598..3e25268638e2 100644 --- a/drivers/iio/accel/st_accel_spi.c +++ b/drivers/iio/accel/st_accel_spi.c @@ -107,8 +107,7 @@ static int st_accel_spi_probe(struct spi_device *spi) struct iio_dev *indio_dev; int err; - st_sensors_of_name_probe(&spi->dev, st_accel_of_match, - spi->modalias, sizeof(spi->modalias)); + st_sensors_dev_name_probe(&spi->dev, spi->modalias, sizeof(spi->modalias)); settings = st_accel_get_settings(spi->modalias); if (!settings) { diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 4a3064fb6cd9..42a71a50650f 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -340,35 +341,6 @@ static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, return pdata; } - -/** - * st_sensors_of_name_probe() - device tree probe for ST sensor name - * @dev: driver model representation of the device. - * @match: the OF match table for the device, containing compatible strings - * but also a .data field with the corresponding internal kernel name - * used by this sensor. - * @name: device name buffer reference. - * @len: device name buffer length. - * - * In effect this function matches a compatible string to an internal kernel - * name for a certain sensor device, so that the rest of the autodetection can - * rely on that name from this point on. I2C/SPI devices will be renamed - * to match the internal kernel convention. - */ -void st_sensors_of_name_probe(struct device *dev, - const struct of_device_id *match, - char *name, int len) -{ - const struct of_device_id *of_id; - - of_id = of_match_device(match, dev); - if (!of_id || !of_id->data) - return; - - /* The name from the OF match takes precedence if present */ - strlcpy(name, of_id->data, len); -} -EXPORT_SYMBOL(st_sensors_of_name_probe); #else static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, struct st_sensors_platform_data *defdata) @@ -377,6 +349,30 @@ static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, } #endif +/** + * st_sensors_dev_name_probe() - device probe for ST sensor name + * @dev: driver model representation of the device. + * @name: device name buffer reference. + * @len: device name buffer length. + * + * In effect this function matches an ID to an internal kernel + * name for a certain sensor device, so that the rest of the autodetection can + * rely on that name from this point on. I2C/SPI devices will be renamed + * to match the internal kernel convention. + */ +void st_sensors_dev_name_probe(struct device *dev, char *name, int len) +{ + const void *match; + + match = device_get_match_data(dev); + if (!match) + return; + + /* The name from the match takes precedence if present */ + strlcpy(name, match, len); +} +EXPORT_SYMBOL(st_sensors_dev_name_probe); + int st_sensors_init_sensor(struct iio_dev *indio_dev, struct st_sensors_platform_data *pdata) { diff --git a/drivers/iio/common/st_sensors/st_sensors_i2c.c b/drivers/iio/common/st_sensors/st_sensors_i2c.c index aa89d54a7c59..286830fb5d35 100644 --- a/drivers/iio/common/st_sensors/st_sensors_i2c.c +++ b/drivers/iio/common/st_sensors/st_sensors_i2c.c @@ -11,8 +11,6 @@ #include #include #include -#include -#include #include #include @@ -68,25 +66,6 @@ int st_sensors_i2c_configure(struct iio_dev *indio_dev, } EXPORT_SYMBOL(st_sensors_i2c_configure); -#ifdef CONFIG_ACPI -int st_sensors_match_acpi_device(struct device *dev) -{ - const struct acpi_device_id *acpi_id; - kernel_ulong_t driver_data = 0; - - if (ACPI_HANDLE(dev)) { - acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev); - if (!acpi_id) { - dev_err(dev, "No driver data\n"); - return -EINVAL; - } - driver_data = acpi_id->driver_data; - } - return driver_data; -} -EXPORT_SYMBOL(st_sensors_match_acpi_device); -#endif - MODULE_AUTHOR("Denis Ciocca "); MODULE_DESCRIPTION("STMicroelectronics ST-sensors i2c driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c index 05a1a0874bd5..bc0010835ac0 100644 --- a/drivers/iio/gyro/st_gyro_i2c.c +++ b/drivers/iio/gyro/st_gyro_i2c.c @@ -70,8 +70,7 @@ static int st_gyro_i2c_probe(struct i2c_client *client, struct iio_dev *indio_dev; int err; - st_sensors_of_name_probe(&client->dev, st_gyro_of_match, - client->name, sizeof(client->name)); + st_sensors_dev_name_probe(&client->dev, client->name, sizeof(client->name)); settings = st_gyro_get_settings(client->name); if (!settings) { diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c index b5c624251231..07224d5bf299 100644 --- a/drivers/iio/gyro/st_gyro_spi.c +++ b/drivers/iio/gyro/st_gyro_spi.c @@ -74,8 +74,7 @@ static int st_gyro_spi_probe(struct spi_device *spi) struct iio_dev *indio_dev; int err; - st_sensors_of_name_probe(&spi->dev, st_gyro_of_match, - spi->modalias, sizeof(spi->modalias)); + st_sensors_dev_name_probe(&spi->dev, spi->modalias, sizeof(spi->modalias)); settings = st_gyro_get_settings(spi->modalias); if (!settings) { diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c index fdba480a12be..bf63777bbc6e 100644 --- a/drivers/iio/magnetometer/st_magn_i2c.c +++ b/drivers/iio/magnetometer/st_magn_i2c.c @@ -62,8 +62,7 @@ static int st_magn_i2c_probe(struct i2c_client *client, struct iio_dev *indio_dev; int err; - st_sensors_of_name_probe(&client->dev, st_magn_of_match, - client->name, sizeof(client->name)); + st_sensors_dev_name_probe(&client->dev, client->name, sizeof(client->name)); settings = st_magn_get_settings(client->name); if (!settings) { diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c index fbf909bde841..78f846fc120e 100644 --- a/drivers/iio/magnetometer/st_magn_spi.c +++ b/drivers/iio/magnetometer/st_magn_spi.c @@ -56,8 +56,7 @@ static int st_magn_spi_probe(struct spi_device *spi) struct iio_dev *indio_dev; int err; - st_sensors_of_name_probe(&spi->dev, st_magn_of_match, - spi->modalias, sizeof(spi->modalias)); + st_sensors_dev_name_probe(&spi->dev, spi->modalias, sizeof(spi->modalias)); settings = st_magn_get_settings(spi->modalias); if (!settings) { diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c index 6203bc9d5c2d..dd1f515ca1f1 100644 --- a/drivers/iio/pressure/st_pressure_i2c.c +++ b/drivers/iio/pressure/st_pressure_i2c.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -83,18 +82,7 @@ static int st_press_i2c_probe(struct i2c_client *client, struct iio_dev *indio_dev; int ret; - if (client->dev.of_node) { - st_sensors_of_name_probe(&client->dev, st_press_of_match, - client->name, sizeof(client->name)); - } else if (ACPI_HANDLE(&client->dev)) { - ret = st_sensors_match_acpi_device(&client->dev); - if ((ret < 0) || (ret >= ST_PRESS_MAX)) - return -ENODEV; - - strlcpy(client->name, st_press_id_table[ret].name, - sizeof(client->name)); - } else if (!id) - return -ENODEV; + st_sensors_dev_name_probe(&client->dev, client->name, sizeof(client->name)); settings = st_press_get_settings(client->name); if (!settings) { diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c index 7c8b70221e70..dd31241bf4b4 100644 --- a/drivers/iio/pressure/st_pressure_spi.c +++ b/drivers/iio/pressure/st_pressure_spi.c @@ -66,8 +66,7 @@ static int st_press_spi_probe(struct spi_device *spi) struct iio_dev *indio_dev; int err; - st_sensors_of_name_probe(&spi->dev, st_press_of_match, - spi->modalias, sizeof(spi->modalias)); + st_sensors_dev_name_probe(&spi->dev, spi->modalias, sizeof(spi->modalias)); settings = st_press_get_settings(spi->modalias); if (!settings) { diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index 686be532f4cb..33e939977444 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -315,16 +315,6 @@ ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, ssize_t st_sensors_sysfs_scale_avail(struct device *dev, struct device_attribute *attr, char *buf); -#ifdef CONFIG_OF -void st_sensors_of_name_probe(struct device *dev, - const struct of_device_id *match, - char *name, int len); -#else -static inline void st_sensors_of_name_probe(struct device *dev, - const struct of_device_id *match, - char *name, int len) -{ -} -#endif +void st_sensors_dev_name_probe(struct device *dev, char *name, int len); #endif /* ST_SENSORS_H */ diff --git a/include/linux/iio/common/st_sensors_i2c.h b/include/linux/iio/common/st_sensors_i2c.h index 01e424e2af4f..5f15cf01036c 100644 --- a/include/linux/iio/common/st_sensors_i2c.h +++ b/include/linux/iio/common/st_sensors_i2c.h @@ -12,18 +12,8 @@ #include #include -#include int st_sensors_i2c_configure(struct iio_dev *indio_dev, struct i2c_client *client); -#ifdef CONFIG_ACPI -int st_sensors_match_acpi_device(struct device *dev); -#else -static inline int st_sensors_match_acpi_device(struct device *dev) -{ - return -ENODEV; -} -#endif - #endif /* ST_SENSORS_I2C_H */ From ecb27c5e430785018199dd42e566711022d32523 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 16 Dec 2019 19:38:53 +0200 Subject: [PATCH 11/29] iio: st_sensors: Make use of device properties Device property API allows to gather device resources from different sources, such as ACPI. Convert the drivers to unleash the power of device property API. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_i2c.c | 6 +----- drivers/iio/accel/st_accel_spi.c | 6 +----- .../iio/common/st_sensors/st_sensors_core.c | 21 +++++-------------- .../iio/common/st_sensors/st_sensors_spi.c | 12 ++++++----- drivers/iio/gyro/st_gyro_i2c.c | 6 +----- drivers/iio/gyro/st_gyro_spi.c | 6 +----- drivers/iio/magnetometer/st_magn_i2c.c | 6 +----- drivers/iio/magnetometer/st_magn_spi.c | 6 +----- drivers/iio/pressure/st_pressure_i2c.c | 6 +----- drivers/iio/pressure/st_pressure_spi.c | 6 +----- 10 files changed, 20 insertions(+), 61 deletions(-) diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index 0f4aef5448e7..633955d764cc 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -18,7 +18,6 @@ #include #include "st_accel.h" -#ifdef CONFIG_OF static const struct of_device_id st_accel_of_match[] = { { /* An older compatible */ @@ -108,9 +107,6 @@ static const struct of_device_id st_accel_of_match[] = { {}, }; MODULE_DEVICE_TABLE(of, st_accel_of_match); -#else -#define st_accel_of_match NULL -#endif #ifdef CONFIG_ACPI static const struct acpi_device_id st_accel_acpi_match[] = { @@ -193,7 +189,7 @@ static int st_accel_i2c_remove(struct i2c_client *client) static struct i2c_driver st_accel_driver = { .driver = { .name = "st-accel-i2c", - .of_match_table = of_match_ptr(st_accel_of_match), + .of_match_table = st_accel_of_match, .acpi_match_table = ACPI_PTR(st_accel_acpi_match), }, .probe_new = st_accel_i2c_probe, diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c index 3e25268638e2..568ff1bae0ee 100644 --- a/drivers/iio/accel/st_accel_spi.c +++ b/drivers/iio/accel/st_accel_spi.c @@ -17,7 +17,6 @@ #include #include "st_accel.h" -#ifdef CONFIG_OF /* * For new single-chip sensors use as compatible string. * For old single-chip devices keep -accel to maintain @@ -96,9 +95,6 @@ static const struct of_device_id st_accel_of_match[] = { {} }; MODULE_DEVICE_TABLE(of, st_accel_of_match); -#else -#define st_accel_of_match NULL -#endif static int st_accel_spi_probe(struct spi_device *spi) { @@ -165,7 +161,7 @@ MODULE_DEVICE_TABLE(spi, st_accel_id_table); static struct spi_driver st_accel_driver = { .driver = { .name = "st-accel-spi", - .of_match_table = of_match_ptr(st_accel_of_match), + .of_match_table = st_accel_of_match, }, .probe = st_accel_spi_probe, .remove = st_accel_spi_remove, diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 42a71a50650f..e051edbc43c1 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -14,8 +14,6 @@ #include #include #include -#include -#include #include #include #include @@ -320,34 +318,25 @@ static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev, return 0; } -#ifdef CONFIG_OF -static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, +static struct st_sensors_platform_data *st_sensors_dev_probe(struct device *dev, struct st_sensors_platform_data *defdata) { struct st_sensors_platform_data *pdata; - struct device_node *np = dev->of_node; u32 val; - if (!np) + if (!dev_fwnode(dev)) return NULL; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!of_property_read_u32(np, "st,drdy-int-pin", &val) && (val <= 2)) + if (!device_property_read_u32(dev, "st,drdy-int-pin", &val) && (val <= 2)) pdata->drdy_int_pin = (u8) val; else pdata->drdy_int_pin = defdata ? defdata->drdy_int_pin : 0; - pdata->open_drain = of_property_read_bool(np, "drive-open-drain"); + pdata->open_drain = device_property_read_bool(dev, "drive-open-drain"); return pdata; } -#else -static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, - struct st_sensors_platform_data *defdata) -{ - return NULL; -} -#endif /** * st_sensors_dev_name_probe() - device probe for ST sensor name @@ -381,7 +370,7 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev, int err = 0; /* If OF/DT pdata exists, it will take precedence of anything else */ - of_pdata = st_sensors_of_probe(indio_dev->dev.parent, pdata); + of_pdata = st_sensors_dev_probe(indio_dev->dev.parent, pdata); if (of_pdata) pdata = of_pdata; diff --git a/drivers/iio/common/st_sensors/st_sensors_spi.c b/drivers/iio/common/st_sensors/st_sensors_spi.c index 2262f81b07c2..1275fb0eda31 100644 --- a/drivers/iio/common/st_sensors/st_sensors_spi.c +++ b/drivers/iio/common/st_sensors/st_sensors_spi.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -37,14 +38,15 @@ static const struct regmap_config st_sensors_spi_regmap_multiread_bit_config = { */ static bool st_sensors_is_spi_3_wire(struct spi_device *spi) { - struct device_node *np = spi->dev.of_node; struct st_sensors_platform_data *pdata; + struct device *dev = &spi->dev; - pdata = (struct st_sensors_platform_data *)spi->dev.platform_data; - if ((np && of_property_read_bool(np, "spi-3wire")) || - (pdata && pdata->spi_3wire)) { + if (device_property_read_bool(dev, "spi-3wire")) + return true; + + pdata = (struct st_sensors_platform_data *)dev->platform_data; + if (pdata && pdata->spi_3wire) return true; - } return false; } diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c index bc0010835ac0..8190966e6ff0 100644 --- a/drivers/iio/gyro/st_gyro_i2c.c +++ b/drivers/iio/gyro/st_gyro_i2c.c @@ -17,7 +17,6 @@ #include #include "st_gyro.h" -#ifdef CONFIG_OF static const struct of_device_id st_gyro_of_match[] = { { .compatible = "st,l3g4200d-gyro", @@ -58,9 +57,6 @@ static const struct of_device_id st_gyro_of_match[] = { {}, }; MODULE_DEVICE_TABLE(of, st_gyro_of_match); -#else -#define st_gyro_of_match NULL -#endif static int st_gyro_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) @@ -121,7 +117,7 @@ MODULE_DEVICE_TABLE(i2c, st_gyro_id_table); static struct i2c_driver st_gyro_driver = { .driver = { .name = "st-gyro-i2c", - .of_match_table = of_match_ptr(st_gyro_of_match), + .of_match_table = st_gyro_of_match, }, .probe = st_gyro_i2c_probe, .remove = st_gyro_i2c_remove, diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c index 07224d5bf299..efb862763ca3 100644 --- a/drivers/iio/gyro/st_gyro_spi.c +++ b/drivers/iio/gyro/st_gyro_spi.c @@ -17,7 +17,6 @@ #include #include "st_gyro.h" -#ifdef CONFIG_OF /* * For new single-chip sensors use as compatible string. * For old single-chip devices keep -gyro to maintain @@ -63,9 +62,6 @@ static const struct of_device_id st_gyro_of_match[] = { {}, }; MODULE_DEVICE_TABLE(of, st_gyro_of_match); -#else -#define st_gyro_of_match NULL -#endif static int st_gyro_spi_probe(struct spi_device *spi) { @@ -125,7 +121,7 @@ MODULE_DEVICE_TABLE(spi, st_gyro_id_table); static struct spi_driver st_gyro_driver = { .driver = { .name = "st-gyro-spi", - .of_match_table = of_match_ptr(st_gyro_of_match), + .of_match_table = st_gyro_of_match, }, .probe = st_gyro_spi_probe, .remove = st_gyro_spi_remove, diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c index bf63777bbc6e..c6bb4ce77594 100644 --- a/drivers/iio/magnetometer/st_magn_i2c.c +++ b/drivers/iio/magnetometer/st_magn_i2c.c @@ -17,7 +17,6 @@ #include #include "st_magn.h" -#ifdef CONFIG_OF static const struct of_device_id st_magn_of_match[] = { { .compatible = "st,lsm303dlh-magn", @@ -50,9 +49,6 @@ static const struct of_device_id st_magn_of_match[] = { {}, }; MODULE_DEVICE_TABLE(of, st_magn_of_match); -#else -#define st_magn_of_match NULL -#endif static int st_magn_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) @@ -112,7 +108,7 @@ MODULE_DEVICE_TABLE(i2c, st_magn_id_table); static struct i2c_driver st_magn_driver = { .driver = { .name = "st-magn-i2c", - .of_match_table = of_match_ptr(st_magn_of_match), + .of_match_table = st_magn_of_match, }, .probe = st_magn_i2c_probe, .remove = st_magn_i2c_remove, diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c index 78f846fc120e..3d08d74c367d 100644 --- a/drivers/iio/magnetometer/st_magn_spi.c +++ b/drivers/iio/magnetometer/st_magn_spi.c @@ -17,7 +17,6 @@ #include #include "st_magn.h" -#ifdef CONFIG_OF /* * For new single-chip sensors use as compatible string. * For old single-chip devices keep -magn to maintain @@ -45,9 +44,6 @@ static const struct of_device_id st_magn_of_match[] = { {} }; MODULE_DEVICE_TABLE(of, st_magn_of_match); -#else -#define st_magn_of_match NULL -#endif static int st_magn_spi_probe(struct spi_device *spi) { @@ -103,7 +99,7 @@ MODULE_DEVICE_TABLE(spi, st_magn_id_table); static struct spi_driver st_magn_driver = { .driver = { .name = "st-magn-spi", - .of_match_table = of_match_ptr(st_magn_of_match), + .of_match_table = st_magn_of_match, }, .probe = st_magn_spi_probe, .remove = st_magn_spi_remove, diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c index dd1f515ca1f1..09c6903f99b8 100644 --- a/drivers/iio/pressure/st_pressure_i2c.c +++ b/drivers/iio/pressure/st_pressure_i2c.c @@ -17,7 +17,6 @@ #include #include "st_pressure.h" -#ifdef CONFIG_OF static const struct of_device_id st_press_of_match[] = { { .compatible = "st,lps001wp-press", @@ -50,9 +49,6 @@ static const struct of_device_id st_press_of_match[] = { {}, }; MODULE_DEVICE_TABLE(of, st_press_of_match); -#else -#define st_press_of_match NULL -#endif #ifdef CONFIG_ACPI static const struct acpi_device_id st_press_acpi_match[] = { @@ -119,7 +115,7 @@ static int st_press_i2c_remove(struct i2c_client *client) static struct i2c_driver st_press_driver = { .driver = { .name = "st-press-i2c", - .of_match_table = of_match_ptr(st_press_of_match), + .of_match_table = st_press_of_match, .acpi_match_table = ACPI_PTR(st_press_acpi_match), }, .probe = st_press_i2c_probe, diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c index dd31241bf4b4..b5ee3ec2764f 100644 --- a/drivers/iio/pressure/st_pressure_spi.c +++ b/drivers/iio/pressure/st_pressure_spi.c @@ -17,7 +17,6 @@ #include #include "st_pressure.h" -#ifdef CONFIG_OF /* * For new single-chip sensors use as compatible string. * For old single-chip devices keep -press to maintain @@ -55,9 +54,6 @@ static const struct of_device_id st_press_of_match[] = { {}, }; MODULE_DEVICE_TABLE(of, st_press_of_match); -#else -#define st_press_of_match NULL -#endif static int st_press_spi_probe(struct spi_device *spi) { @@ -115,7 +111,7 @@ MODULE_DEVICE_TABLE(spi, st_press_id_table); static struct spi_driver st_press_driver = { .driver = { .name = "st-press-spi", - .of_match_table = of_match_ptr(st_press_of_match), + .of_match_table = st_press_of_match, }, .probe = st_press_spi_probe, .remove = st_press_spi_remove, From dc26935fb60e8da8d59655dd2ec0de47b20d7d8f Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Wed, 27 Nov 2019 14:07:29 +0100 Subject: [PATCH 12/29] iio: adc: stm32-dfsdm: fix single conversion Apply data formatting to single conversion, as this is already done in continuous and trigger modes. Fixes: 102afde62937 ("iio: adc: stm32-dfsdm: manage data resolution in trigger mode") Signed-off-by: Olivier Moysan Cc: Acked-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-dfsdm-adc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index 74a2211bdff4..1c9b05d11dc5 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -1204,6 +1204,8 @@ static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev, stm32_dfsdm_stop_conv(adc); + stm32_dfsdm_process_data(adc, res); + stop_dfsdm: stm32_dfsdm_stop_dfsdm(adc->dfsdm); From f81ec5bf0cab29693980abbc983d0971e0efb0ea Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Wed, 27 Nov 2019 14:10:08 +0100 Subject: [PATCH 13/29] iio: adc: stm32-dfsdm: adapt sampling rate to oversampling ratio Update sampling rate when oversampling ratio is changed through the IIO ABI. Signed-off-by: Olivier Moysan Acked-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-dfsdm-adc.c | 32 ++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index 1c9b05d11dc5..2aad2cda6943 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -1221,14 +1221,32 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev, unsigned int spi_freq; int ret = -EINVAL; + switch (ch->src) { + case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL: + spi_freq = adc->dfsdm->spi_master_freq; + break; + case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_FALLING: + case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_RISING: + spi_freq = adc->dfsdm->spi_master_freq / 2; + break; + default: + spi_freq = adc->spi_freq; + } + switch (mask) { case IIO_CHAN_INFO_OVERSAMPLING_RATIO: ret = iio_device_claim_direct_mode(indio_dev); if (ret) return ret; + ret = stm32_dfsdm_compute_all_osrs(indio_dev, val); - if (!ret) + if (!ret) { + dev_dbg(&indio_dev->dev, + "Sampling rate changed from (%u) to (%u)\n", + adc->sample_freq, spi_freq / val); adc->oversamp = val; + adc->sample_freq = spi_freq / val; + } iio_device_release_direct_mode(indio_dev); return ret; @@ -1240,18 +1258,6 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev, if (ret) return ret; - switch (ch->src) { - case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL: - spi_freq = adc->dfsdm->spi_master_freq; - break; - case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_FALLING: - case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_RISING: - spi_freq = adc->dfsdm->spi_master_freq / 2; - break; - default: - spi_freq = adc->spi_freq; - } - ret = dfsdm_adc_set_samp_freq(indio_dev, val, spi_freq); iio_device_release_direct_mode(indio_dev); return ret; From a4e6f40c77afe6e6a0076c4bcf7cbf68406a7d9f Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Tue, 10 Dec 2019 16:07:55 +0200 Subject: [PATCH 14/29] iio: imu: adis: use new `delay` structure for SPI transfer delays In a recent change to the SPI subsystem [1], a new `delay` struct was added to replace the `delay_usecs`. This change replaces the current `delay_usecs` with `delay` for this driver. The `spi_transfer_delay_exec()` function [in the SPI framework] makes sure that both `delay_usecs` & `delay` are used (in this order to preserve backwards compatibility). [1] commit bebcfd272df6485 ("spi: introduce `delay` field for `spi_transfer` + spi_transfer_delay_exec()") Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 8f0867495ef5..022bb54fb748 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -45,7 +45,8 @@ int __adis_write_reg(struct adis *adis, unsigned int reg, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = adis->data->write_delay, + .delay.value = adis->data->write_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, .cs_change_delay.value = adis->data->cs_change_delay, .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { @@ -53,7 +54,8 @@ int __adis_write_reg(struct adis *adis, unsigned int reg, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = adis->data->write_delay, + .delay.value = adis->data->write_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, .cs_change_delay.value = adis->data->cs_change_delay, .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { @@ -61,19 +63,22 @@ int __adis_write_reg(struct adis *adis, unsigned int reg, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = adis->data->write_delay, + .delay.value = adis->data->write_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, .cs_change_delay.value = adis->data->cs_change_delay, .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 6, .bits_per_word = 8, .len = 2, - .delay_usecs = adis->data->write_delay, + .delay.value = adis->data->write_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 8, .bits_per_word = 8, .len = 2, - .delay_usecs = adis->data->write_delay, + .delay.value = adis->data->write_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, }, }; @@ -140,7 +145,8 @@ int __adis_read_reg(struct adis *adis, unsigned int reg, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = adis->data->write_delay, + .delay.value = adis->data->write_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, .cs_change_delay.value = adis->data->cs_change_delay, .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { @@ -148,7 +154,8 @@ int __adis_read_reg(struct adis *adis, unsigned int reg, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = adis->data->read_delay, + .delay.value = adis->data->read_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, .cs_change_delay.value = adis->data->cs_change_delay, .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { @@ -157,14 +164,16 @@ int __adis_read_reg(struct adis *adis, unsigned int reg, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = adis->data->read_delay, + .delay.value = adis->data->read_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, .cs_change_delay.value = adis->data->cs_change_delay, .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { .rx_buf = adis->rx + 2, .bits_per_word = 8, .len = 2, - .delay_usecs = adis->data->read_delay, + .delay.value = adis->data->read_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, }, }; From da4d3d6bb9f6047217d549c233303161bb4678d9 Mon Sep 17 00:00:00 2001 From: Alexandru Tachici Date: Mon, 13 Jan 2020 12:26:52 +0200 Subject: [PATCH 15/29] iio: adc: ad-sigma-delta: Allow custom IRQ flags Before this patch the ad_sigma_delta implementation hardcoded the irq trigger type to low, assuming that all Sigma-Delta ADCs have the same interrupt-type. This patch allows all drivers using the ad_sigma_delta layer to set the irq trigger type to the one specified in the datasheet. Signed-off-by: Alexandru Tachici Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7124.c | 2 ++ drivers/iio/adc/ad7780.c | 1 + drivers/iio/adc/ad7791.c | 1 + drivers/iio/adc/ad7793.c | 1 + drivers/iio/adc/ad_sigma_delta.c | 2 +- include/linux/iio/adc/ad_sigma_delta.h | 2 ++ 6 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index 3f03abf100b5..63df2e2a8caf 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -224,6 +225,7 @@ static const struct ad_sigma_delta_info ad7124_sigma_delta_info = { .addr_shift = 0, .read_mask = BIT(6), .data_reg = AD7124_DATA, + .irq_flags = IRQF_TRIGGER_LOW, }; static int ad7124_set_channel_odr(struct ad7124_state *st, diff --git a/drivers/iio/adc/ad7780.c b/drivers/iio/adc/ad7780.c index 217a5a5c3c6d..291c1a898129 100644 --- a/drivers/iio/adc/ad7780.c +++ b/drivers/iio/adc/ad7780.c @@ -203,6 +203,7 @@ static const struct ad_sigma_delta_info ad7780_sigma_delta_info = { .set_mode = ad7780_set_mode, .postprocess_sample = ad7780_postprocess_sample, .has_registers = false, + .irq_flags = IRQF_TRIGGER_LOW, }; #define AD7780_CHANNEL(bits, wordsize) \ diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c index 54025ea10239..abb239392631 100644 --- a/drivers/iio/adc/ad7791.c +++ b/drivers/iio/adc/ad7791.c @@ -205,6 +205,7 @@ static const struct ad_sigma_delta_info ad7791_sigma_delta_info = { .has_registers = true, .addr_shift = 4, .read_mask = BIT(3), + .irq_flags = IRQF_TRIGGER_LOW, }; static int ad7791_read_raw(struct iio_dev *indio_dev, diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c index bbc41ecf0d2f..b747db97f78a 100644 --- a/drivers/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c @@ -206,6 +206,7 @@ static const struct ad_sigma_delta_info ad7793_sigma_delta_info = { .has_registers = true, .addr_shift = 3, .read_mask = BIT(6), + .irq_flags = IRQF_TRIGGER_LOW, }; static const struct ad_sd_calib_data ad7793_calib_arr[6] = { diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index 8ba90486c787..8115b6de1d6c 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -500,7 +500,7 @@ static int ad_sd_probe_trigger(struct iio_dev *indio_dev) ret = request_irq(sigma_delta->spi->irq, ad_sd_data_rdy_trig_poll, - IRQF_TRIGGER_LOW, + sigma_delta->info->irq_flags, indio_dev->name, sigma_delta); if (ret) diff --git a/include/linux/iio/adc/ad_sigma_delta.h b/include/linux/iio/adc/ad_sigma_delta.h index 8a4e25a7080c..5a127c0ed200 100644 --- a/include/linux/iio/adc/ad_sigma_delta.h +++ b/include/linux/iio/adc/ad_sigma_delta.h @@ -40,6 +40,7 @@ struct iio_dev; * @read_mask: Mask for the communications register having the read bit set. * @data_reg: Address of the data register, if 0 the default address of 0x3 will * be used. + * @irq_flags: flags for the interrupt used by the triggered buffer */ struct ad_sigma_delta_info { int (*set_channel)(struct ad_sigma_delta *, unsigned int channel); @@ -49,6 +50,7 @@ struct ad_sigma_delta_info { unsigned int addr_shift; unsigned int read_mask; unsigned int data_reg; + unsigned long irq_flags; }; /** From 79ef91493f5494e9ddbad85bf571ec03940a7f5c Mon Sep 17 00:00:00 2001 From: Alexandru Tachici Date: Mon, 13 Jan 2020 12:26:53 +0200 Subject: [PATCH 16/29] iio: adc: ad7124: Set IRQ type to falling Ad7124 data-sheet specifies that the falling edge of the DOUT line should be used for an interrupt. The current irq flag (IRQF_TRIGGER_LOW) used will cause unwanted behaviour. When enabling the interrupt it will fire once because the DOUT line is already low. This will make the driver to read an unfinished conversion from the chip. This patch sets the irq type to the one specified in the data-sheet. Signed-off-by: Alexandru Tachici Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7124.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index 63df2e2a8caf..52f45b13da4a 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -225,7 +225,7 @@ static const struct ad_sigma_delta_info ad7124_sigma_delta_info = { .addr_shift = 0, .read_mask = BIT(6), .data_reg = AD7124_DATA, - .irq_flags = IRQF_TRIGGER_LOW, + .irq_flags = IRQF_TRIGGER_FALLING, }; static int ad7124_set_channel_odr(struct ad7124_state *st, From 608184788502fd475e7bca4b1692fda5f0fef5b6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 15 Jan 2020 19:44:24 +0200 Subject: [PATCH 17/29] iio: magnetometer: ak8975: Get rid of platform data Since IIO framework supports device property API and driver has been moved already to the use of GPIO descriptors the logical continuation is to get rid of platform data completely. We are on the safe side here since there are no users of it in the kernel. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/ak8975.c | 14 +++----------- include/linux/iio/magnetometer/ak8975.h | 15 --------------- 2 files changed, 3 insertions(+), 26 deletions(-) delete mode 100644 include/linux/iio/magnetometer/ak8975.h diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 55cffaa82456..8e50e073bcbf 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -28,8 +28,6 @@ #include #include -#include - /* * Register definitions, as well as various shifts and masks to get at the * individual fields of the registers. @@ -857,8 +855,6 @@ static int ak8975_probe(struct i2c_client *client, int err; const char *name = NULL; enum asahi_compass_chipset chipset = AK_MAX_TYPE; - const struct ak8975_platform_data *pdata = - dev_get_platdata(&client->dev); /* * Grab and set up the supplied GPIO. @@ -883,13 +879,9 @@ static int ak8975_probe(struct i2c_client *client, data->eoc_gpiod = eoc_gpiod; data->eoc_irq = 0; - if (!pdata) { - err = iio_read_mount_matrix(&client->dev, "mount-matrix", - &data->orientation); - if (err) - return err; - } else - data->orientation = pdata->orientation; + err = iio_read_mount_matrix(&client->dev, "mount-matrix", &data->orientation); + if (err) + return err; /* id will be NULL when enumerated via ACPI */ if (id) { diff --git a/include/linux/iio/magnetometer/ak8975.h b/include/linux/iio/magnetometer/ak8975.h deleted file mode 100644 index df3697183800..000000000000 --- a/include/linux/iio/magnetometer/ak8975.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __IIO_MAGNETOMETER_AK8975_H__ -#define __IIO_MAGNETOMETER_AK8975_H__ - -#include - -/** - * struct ak8975_platform_data - AK8975 magnetometer driver platform data - * @orientation: mounting matrix relative to main hardware - */ -struct ak8975_platform_data { - struct iio_mount_matrix orientation; -}; - -#endif From 71f221f8a0cd73f985e37d8a05dea2d63eb95b71 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 15 Jan 2020 19:44:25 +0200 Subject: [PATCH 18/29] iio: magnetometer: ak8975: Convert to use device_get_match_data() Convert to use device_get_match_data() instead of open coded variant. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/ak8975.c | 39 +++++++++++++------------------ 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 8e50e073bcbf..3c881541ae72 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -203,11 +203,11 @@ static long ak09912_raw_to_gauss(u16 data) /* Compatible Asahi Kasei Compass parts */ enum asahi_compass_chipset { + AKXXXX = 0, AK8975, AK8963, AK09911, AK09912, - AK_MAX_TYPE }; enum ak_ctrl_reg_addr { @@ -245,7 +245,7 @@ struct ak_def { u8 data_regs[3]; }; -static const struct ak_def ak_def_array[AK_MAX_TYPE] = { +static const struct ak_def ak_def_array[] = { { .type = AK8975, .raw_to_gauss = ak8975_raw_to_gauss, @@ -781,19 +781,6 @@ static const struct acpi_device_id ak_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, ak_acpi_match); #endif -static const char *ak8975_match_acpi_device(struct device *dev, - enum asahi_compass_chipset *chipset) -{ - const struct acpi_device_id *id; - - id = acpi_match_device(dev->driver->acpi_match_table, dev); - if (!id) - return NULL; - *chipset = (int)id->driver_data; - - return dev_name(dev); -} - static void ak8975_fill_buffer(struct iio_dev *indio_dev) { struct ak8975_data *data = iio_priv(indio_dev); @@ -852,9 +839,11 @@ static int ak8975_probe(struct i2c_client *client, struct ak8975_data *data; struct iio_dev *indio_dev; struct gpio_desc *eoc_gpiod; + const void *match; + unsigned int i; int err; + enum asahi_compass_chipset chipset; const char *name = NULL; - enum asahi_compass_chipset chipset = AK_MAX_TYPE; /* * Grab and set up the supplied GPIO. @@ -884,23 +873,27 @@ static int ak8975_probe(struct i2c_client *client, return err; /* id will be NULL when enumerated via ACPI */ - if (id) { + match = device_get_match_data(&client->dev); + if (match) { + chipset = (enum asahi_compass_chipset)(match); + name = dev_name(&client->dev); + } else if (id) { chipset = (enum asahi_compass_chipset)(id->driver_data); name = id->name; - } else if (ACPI_HANDLE(&client->dev)) { - name = ak8975_match_acpi_device(&client->dev, &chipset); - if (!name) - return -ENODEV; } else return -ENOSYS; - if (chipset >= AK_MAX_TYPE) { + for (i = 0; i < ARRAY_SIZE(ak_def_array); i++) + if (ak_def_array[i].type == chipset) + break; + + if (i == ARRAY_SIZE(ak_def_array)) { dev_err(&client->dev, "AKM device type unsupported: %d\n", chipset); return -ENODEV; } - data->def = &ak_def_array[chipset]; + data->def = &ak_def_array[i]; /* Fetch the regulators */ data->vdd = devm_regulator_get(&client->dev, "vdd"); From 2e4c0a5e25768097ecdb514ef453b423e932beea Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Maneyrol Date: Thu, 16 Jan 2020 18:56:45 +0100 Subject: [PATCH 19/29] iio: imu: inv_mpu6050: add fifo temperature data support Add support of temperature data in fifo for all chips. Enable unification of scan elements for icm20602. Add macros for generating scan elements. Signed-off-by: Jean-Baptiste Maneyrol Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 200 +++++++----------- drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 22 +- drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 6 +- drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 3 + 4 files changed, 90 insertions(+), 141 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 268240644adf..1eb3c263b528 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -104,6 +104,7 @@ static const struct inv_mpu6050_chip_config chip_config_6050 = { .divider = INV_MPU6050_FIFO_RATE_TO_DIVIDER(INV_MPU6050_INIT_FIFO_RATE), .gyro_fifo_enable = false, .accl_fifo_enable = false, + .temp_fifo_enable = false, .magn_fifo_enable = false, .accl_fs = INV_MPU6050_FS_02G, .user_ctrl = 0, @@ -856,19 +857,27 @@ static const struct iio_chan_spec_ext_info inv_ext_info[] = { .ext_info = inv_ext_info, \ } +#define INV_MPU6050_TEMP_CHAN(_index) \ + { \ + .type = IIO_TEMP, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \ + | BIT(IIO_CHAN_INFO_OFFSET) \ + | BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .shift = 0, \ + .endianness = IIO_BE, \ + }, \ + } + static const struct iio_chan_spec inv_mpu_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(INV_MPU6050_SCAN_TIMESTAMP), - /* - * Note that temperature should only be via polled reading only, - * not the final scan elements output. - */ - { - .type = IIO_TEMP, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) - | BIT(IIO_CHAN_INFO_OFFSET) - | BIT(IIO_CHAN_INFO_SCALE), - .scan_index = -1, - }, + + INV_MPU6050_TEMP_CHAN(INV_MPU6050_SCAN_TEMP), + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X), INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y), INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z), @@ -878,22 +887,29 @@ static const struct iio_chan_spec inv_mpu_channels[] = { INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z), }; +#define INV_MPU6050_SCAN_MASK_3AXIS_ACCEL \ + (BIT(INV_MPU6050_SCAN_ACCL_X) \ + | BIT(INV_MPU6050_SCAN_ACCL_Y) \ + | BIT(INV_MPU6050_SCAN_ACCL_Z)) + +#define INV_MPU6050_SCAN_MASK_3AXIS_GYRO \ + (BIT(INV_MPU6050_SCAN_GYRO_X) \ + | BIT(INV_MPU6050_SCAN_GYRO_Y) \ + | BIT(INV_MPU6050_SCAN_GYRO_Z)) + +#define INV_MPU6050_SCAN_MASK_TEMP (BIT(INV_MPU6050_SCAN_TEMP)) + static const unsigned long inv_mpu_scan_masks[] = { /* 3-axis accel */ - BIT(INV_MPU6050_SCAN_ACCL_X) - | BIT(INV_MPU6050_SCAN_ACCL_Y) - | BIT(INV_MPU6050_SCAN_ACCL_Z), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL, + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_TEMP, /* 3-axis gyro */ - BIT(INV_MPU6050_SCAN_GYRO_X) - | BIT(INV_MPU6050_SCAN_GYRO_Y) - | BIT(INV_MPU6050_SCAN_GYRO_Z), + INV_MPU6050_SCAN_MASK_3AXIS_GYRO, + INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU6050_SCAN_MASK_TEMP, /* 6-axis accel + gyro */ - BIT(INV_MPU6050_SCAN_ACCL_X) - | BIT(INV_MPU6050_SCAN_ACCL_Y) - | BIT(INV_MPU6050_SCAN_ACCL_Z) - | BIT(INV_MPU6050_SCAN_GYRO_X) - | BIT(INV_MPU6050_SCAN_GYRO_Y) - | BIT(INV_MPU6050_SCAN_GYRO_Z), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO, + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO + | INV_MPU6050_SCAN_MASK_TEMP, 0, }; @@ -917,17 +933,9 @@ static const unsigned long inv_mpu_scan_masks[] = { static const struct iio_chan_spec inv_mpu9150_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(INV_MPU9X50_SCAN_TIMESTAMP), - /* - * Note that temperature should only be via polled reading only, - * not the final scan elements output. - */ - { - .type = IIO_TEMP, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) - | BIT(IIO_CHAN_INFO_OFFSET) - | BIT(IIO_CHAN_INFO_SCALE), - .scan_index = -1, - }, + + INV_MPU6050_TEMP_CHAN(INV_MPU6050_SCAN_TEMP), + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X), INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y), INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z), @@ -944,17 +952,9 @@ static const struct iio_chan_spec inv_mpu9150_channels[] = { static const struct iio_chan_spec inv_mpu9250_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(INV_MPU9X50_SCAN_TIMESTAMP), - /* - * Note that temperature should only be via polled reading only, - * not the final scan elements output. - */ - { - .type = IIO_TEMP, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) - | BIT(IIO_CHAN_INFO_OFFSET) - | BIT(IIO_CHAN_INFO_SCALE), - .scan_index = -1, - }, + + INV_MPU6050_TEMP_CHAN(INV_MPU6050_SCAN_TEMP), + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X), INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y), INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z), @@ -969,98 +969,50 @@ static const struct iio_chan_spec inv_mpu9250_channels[] = { INV_MPU9X50_MAGN_CHAN(IIO_MOD_Z, 16, INV_MPU9X50_SCAN_MAGN_Z), }; +#define INV_MPU9X50_SCAN_MASK_3AXIS_MAGN \ + (BIT(INV_MPU9X50_SCAN_MAGN_X) \ + | BIT(INV_MPU9X50_SCAN_MAGN_Y) \ + | BIT(INV_MPU9X50_SCAN_MAGN_Z)) + static const unsigned long inv_mpu9x50_scan_masks[] = { /* 3-axis accel */ - BIT(INV_MPU6050_SCAN_ACCL_X) - | BIT(INV_MPU6050_SCAN_ACCL_Y) - | BIT(INV_MPU6050_SCAN_ACCL_Z), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL, + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_TEMP, /* 3-axis gyro */ - BIT(INV_MPU6050_SCAN_GYRO_X) - | BIT(INV_MPU6050_SCAN_GYRO_Y) - | BIT(INV_MPU6050_SCAN_GYRO_Z), + INV_MPU6050_SCAN_MASK_3AXIS_GYRO, + INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU6050_SCAN_MASK_TEMP, /* 3-axis magn */ - BIT(INV_MPU9X50_SCAN_MAGN_X) - | BIT(INV_MPU9X50_SCAN_MAGN_Y) - | BIT(INV_MPU9X50_SCAN_MAGN_Z), + INV_MPU9X50_SCAN_MASK_3AXIS_MAGN, + INV_MPU9X50_SCAN_MASK_3AXIS_MAGN | INV_MPU6050_SCAN_MASK_TEMP, /* 6-axis accel + gyro */ - BIT(INV_MPU6050_SCAN_ACCL_X) - | BIT(INV_MPU6050_SCAN_ACCL_Y) - | BIT(INV_MPU6050_SCAN_ACCL_Z) - | BIT(INV_MPU6050_SCAN_GYRO_X) - | BIT(INV_MPU6050_SCAN_GYRO_Y) - | BIT(INV_MPU6050_SCAN_GYRO_Z), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO, + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO + | INV_MPU6050_SCAN_MASK_TEMP, /* 6-axis accel + magn */ - BIT(INV_MPU6050_SCAN_ACCL_X) - | BIT(INV_MPU6050_SCAN_ACCL_Y) - | BIT(INV_MPU6050_SCAN_ACCL_Z) - | BIT(INV_MPU9X50_SCAN_MAGN_X) - | BIT(INV_MPU9X50_SCAN_MAGN_Y) - | BIT(INV_MPU9X50_SCAN_MAGN_Z), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN, + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN + | INV_MPU6050_SCAN_MASK_TEMP, /* 6-axis gyro + magn */ - BIT(INV_MPU6050_SCAN_GYRO_X) - | BIT(INV_MPU6050_SCAN_GYRO_Y) - | BIT(INV_MPU6050_SCAN_GYRO_Z) - | BIT(INV_MPU9X50_SCAN_MAGN_X) - | BIT(INV_MPU9X50_SCAN_MAGN_Y) - | BIT(INV_MPU9X50_SCAN_MAGN_Z), + INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN, + INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN + | INV_MPU6050_SCAN_MASK_TEMP, /* 9-axis accel + gyro + magn */ - BIT(INV_MPU6050_SCAN_ACCL_X) - | BIT(INV_MPU6050_SCAN_ACCL_Y) - | BIT(INV_MPU6050_SCAN_ACCL_Z) - | BIT(INV_MPU6050_SCAN_GYRO_X) - | BIT(INV_MPU6050_SCAN_GYRO_Y) - | BIT(INV_MPU6050_SCAN_GYRO_Z) - | BIT(INV_MPU9X50_SCAN_MAGN_X) - | BIT(INV_MPU9X50_SCAN_MAGN_Y) - | BIT(INV_MPU9X50_SCAN_MAGN_Z), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO + | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN, + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO + | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN + | INV_MPU6050_SCAN_MASK_TEMP, 0, }; -static const struct iio_chan_spec inv_icm20602_channels[] = { - IIO_CHAN_SOFT_TIMESTAMP(INV_ICM20602_SCAN_TIMESTAMP), - { - .type = IIO_TEMP, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) - | BIT(IIO_CHAN_INFO_OFFSET) - | BIT(IIO_CHAN_INFO_SCALE), - .scan_index = INV_ICM20602_SCAN_TEMP, - .scan_type = { - .sign = 's', - .realbits = 16, - .storagebits = 16, - .shift = 0, - .endianness = IIO_BE, - }, - }, - - INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_ICM20602_SCAN_GYRO_X), - INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_ICM20602_SCAN_GYRO_Y), - INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_ICM20602_SCAN_GYRO_Z), - - INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Y, INV_ICM20602_SCAN_ACCL_Y), - INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_X, INV_ICM20602_SCAN_ACCL_X), - INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_ICM20602_SCAN_ACCL_Z), -}; - static const unsigned long inv_icm20602_scan_masks[] = { /* 3-axis accel + temp (mandatory) */ - BIT(INV_ICM20602_SCAN_ACCL_X) - | BIT(INV_ICM20602_SCAN_ACCL_Y) - | BIT(INV_ICM20602_SCAN_ACCL_Z) - | BIT(INV_ICM20602_SCAN_TEMP), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_TEMP, /* 3-axis gyro + temp (mandatory) */ - BIT(INV_ICM20602_SCAN_GYRO_X) - | BIT(INV_ICM20602_SCAN_GYRO_Y) - | BIT(INV_ICM20602_SCAN_GYRO_Z) - | BIT(INV_ICM20602_SCAN_TEMP), + INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU6050_SCAN_MASK_TEMP, /* 6-axis accel + gyro + temp (mandatory) */ - BIT(INV_ICM20602_SCAN_ACCL_X) - | BIT(INV_ICM20602_SCAN_ACCL_Y) - | BIT(INV_ICM20602_SCAN_ACCL_Z) - | BIT(INV_ICM20602_SCAN_GYRO_X) - | BIT(INV_ICM20602_SCAN_GYRO_Y) - | BIT(INV_ICM20602_SCAN_GYRO_Z) - | BIT(INV_ICM20602_SCAN_TEMP), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO + | INV_MPU6050_SCAN_MASK_TEMP, 0, }; @@ -1363,8 +1315,8 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, indio_dev->available_scan_masks = inv_mpu9x50_scan_masks; break; case INV_ICM20602: - indio_dev->channels = inv_icm20602_channels; - indio_dev->num_channels = ARRAY_SIZE(inv_icm20602_channels); + indio_dev->channels = inv_mpu_channels; + indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels); indio_dev->available_scan_masks = inv_icm20602_scan_masks; break; default: diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index b096e010d4ee..6158fca7f70e 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -86,6 +86,7 @@ enum inv_devices { * @accl_fs: accel full scale range. * @accl_fifo_enable: enable accel data output * @gyro_fifo_enable: enable gyro data output + * @temp_fifo_enable: enable temp data output * @magn_fifo_enable: enable magn data output * @divider: chip sample rate divider (sample rate divider - 1) */ @@ -95,6 +96,7 @@ struct inv_mpu6050_chip_config { unsigned int accl_fs:2; unsigned int accl_fifo_enable:1; unsigned int gyro_fifo_enable:1; + unsigned int temp_fifo_enable:1; unsigned int magn_fifo_enable:1; u8 divider; u8 user_ctrl; @@ -184,6 +186,7 @@ struct inv_mpu6050_state { #define INV_MPU6050_BIT_SLAVE_2 0x04 #define INV_MPU6050_BIT_ACCEL_OUT 0x08 #define INV_MPU6050_BITS_GYRO_OUT 0x70 +#define INV_MPU6050_BIT_TEMP_OUT 0x80 #define INV_MPU6050_REG_I2C_MST_CTRL 0x24 #define INV_MPU6050_BITS_I2C_MST_CLK_400KHZ 0x0D @@ -268,8 +271,8 @@ struct inv_mpu6050_state { /* MPU9X50 9-axis magnetometer */ #define INV_MPU9X50_BYTES_MAGN 7 -/* ICM20602 FIFO samples include temperature readings */ -#define INV_ICM20602_BYTES_PER_TEMP_SENSOR 2 +/* FIFO temperature sample size */ +#define INV_MPU6050_BYTES_PER_TEMP_SENSOR 2 /* mpu6500 registers */ #define INV_MPU6500_REG_ACCEL_CONFIG_2 0x1D @@ -298,7 +301,7 @@ struct inv_mpu6050_state { #define INV_ICM20608_TEMP_OFFSET 8170 #define INV_ICM20608_TEMP_SCALE 3059976 -/* 6 + 6 + 7 (for MPU9x50) = 19 round up to 24 and plus 8 */ +/* 6 + 6 + 2 + 7 (for MPU9x50) = 21 round up to 24 and plus 8 */ #define INV_MPU6050_OUTPUT_DATA_SIZE 32 #define INV_MPU6050_REG_INT_PIN_CFG 0x37 @@ -344,6 +347,7 @@ enum inv_mpu6050_scan { INV_MPU6050_SCAN_ACCL_X, INV_MPU6050_SCAN_ACCL_Y, INV_MPU6050_SCAN_ACCL_Z, + INV_MPU6050_SCAN_TEMP, INV_MPU6050_SCAN_GYRO_X, INV_MPU6050_SCAN_GYRO_Y, INV_MPU6050_SCAN_GYRO_Z, @@ -355,18 +359,6 @@ enum inv_mpu6050_scan { INV_MPU9X50_SCAN_TIMESTAMP, }; -/* scan element definition for ICM20602, which includes temperature */ -enum inv_icm20602_scan { - INV_ICM20602_SCAN_ACCL_X, - INV_ICM20602_SCAN_ACCL_Y, - INV_ICM20602_SCAN_ACCL_Z, - INV_ICM20602_SCAN_TEMP, - INV_ICM20602_SCAN_GYRO_X, - INV_ICM20602_SCAN_GYRO_Y, - INV_ICM20602_SCAN_GYRO_Z, - INV_ICM20602_SCAN_TIMESTAMP, -}; - enum inv_mpu6050_filter_e { INV_MPU6050_FILTER_256HZ_NOLPF2 = 0, INV_MPU6050_FILTER_188HZ, diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c index 10d16ec5104b..3755577dc449 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c @@ -142,6 +142,8 @@ int inv_reset_fifo(struct iio_dev *indio_dev) d |= INV_MPU6050_BITS_GYRO_OUT; if (st->chip_config.accl_fifo_enable) d |= INV_MPU6050_BIT_ACCEL_OUT; + if (st->chip_config.temp_fifo_enable) + d |= INV_MPU6050_BIT_TEMP_OUT; if (st->chip_config.magn_fifo_enable) d |= INV_MPU6050_BIT_SLAVE_0; result = regmap_write(st->map, st->reg->fifo_en, d); @@ -200,8 +202,8 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) if (st->chip_config.gyro_fifo_enable) bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR; - if (st->chip_type == INV_ICM20602) - bytes_per_datum += INV_ICM20602_BYTES_PER_TEMP_SENSOR; + if (st->chip_config.temp_fifo_enable) + bytes_per_datum += INV_MPU6050_BYTES_PER_TEMP_SENSOR; if (st->chip_config.magn_fifo_enable) bytes_per_datum += INV_MPU9X50_BYTES_MAGN; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c index a9c75bc62f18..5199fe790c30 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c @@ -24,6 +24,9 @@ static void inv_scan_query_mpu6050(struct iio_dev *indio_dev) indio_dev->active_scan_mask) || test_bit(INV_MPU6050_SCAN_ACCL_Z, indio_dev->active_scan_mask); + + st->chip_config.temp_fifo_enable = + test_bit(INV_MPU6050_SCAN_TEMP, indio_dev->active_scan_mask); } static void inv_scan_query_mpu9x50(struct iio_dev *indio_dev) From 84961af78c509d500b9b4a45989e449f048c821a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= Date: Sat, 11 Jan 2020 16:19:11 +0100 Subject: [PATCH 20/29] iio: imu/mpu6050: support dual-edge IRQ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make mpu6050 usable on platforms which provide only any-edge interrupts. One example of this kind of platform is AT91SAM9G45 Signed-off-by: Michał Mirosław Acked-by: Jean-Baptiste Maneyrol Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 2 +- drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 1eb3c263b528..5096fc49012d 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -1220,7 +1220,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, irq_type = irqd_get_trigger_type(desc); if (!irq_type) irq_type = IRQF_TRIGGER_RISING; - if (irq_type == IRQF_TRIGGER_RISING) + if (irq_type & IRQF_TRIGGER_RISING) // rising or both-edge st->irq_mask = INV_MPU6050_ACTIVE_HIGH; else if (irq_type == IRQF_TRIGGER_FALLING) st->irq_mask = INV_MPU6050_ACTIVE_LOW; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c index 3755577dc449..f9fdf4302a91 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c @@ -185,11 +185,8 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) "failed to ack interrupt\n"); goto flush_fifo; } - if (!(int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT)) { - dev_warn(regmap_get_device(st->map), - "spurious interrupt with status 0x%x\n", int_status); + if (!(int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT)) goto end_session; - } if (!(st->chip_config.accl_fifo_enable | st->chip_config.gyro_fifo_enable | From 98496ccdf0dd88696203e69542e07ef824c56ead Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 16 Jan 2020 13:08:29 +0300 Subject: [PATCH 21/29] iio: accel: bma400: prevent setting accel scale too low This puts an upper bound on "val2" but it also needs to have a lower bound (BMA400_SCALE_MIN). Fixes: 465c811f1f20 ("iio: accel: Add driver for the BMA400") Signed-off-by: Dan Carpenter Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bma400_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c index ab4a158b35af..cc77f89c048b 100644 --- a/drivers/iio/accel/bma400_core.c +++ b/drivers/iio/accel/bma400_core.c @@ -752,7 +752,8 @@ static int bma400_write_raw(struct iio_dev *indio_dev, mutex_unlock(&data->mutex); return ret; case IIO_CHAN_INFO_SCALE: - if (val != 0 || val2 > BMA400_SCALE_MAX) + if (val != 0 || + val2 < BMA400_SCALE_MIN || val2 > BMA400_SCALE_MAX) return -EINVAL; mutex_lock(&data->mutex); From 80cbc848c4fa03580954ab6598e415b6b56a66ac Mon Sep 17 00:00:00 2001 From: Stefan Popa Date: Thu, 16 Jan 2020 15:11:47 +0200 Subject: [PATCH 22/29] iio: imu: adis16480: Add support for ADIS16490 The ADIS16490 is part of the same family with ADIS16495 and ADIS16497, the main difference is the temperature, accelerometer and gyroscope scales. Datasheet: Link: https://www.analog.com/media/en/technical-documentation/data-sheets/adis16490.pdf Signed-off-by: Stefan Popa Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis16480.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c index f0ad7ce64861..dac87f1001fd 100644 --- a/drivers/iio/imu/adis16480.c +++ b/drivers/iio/imu/adis16480.c @@ -787,6 +787,7 @@ enum adis16480_variant { ADIS16480, ADIS16485, ADIS16488, + ADIS16490, ADIS16495_1, ADIS16495_2, ADIS16495_3, @@ -878,6 +879,20 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .filter_freqs = adis16480_def_filter_freqs, .timeouts = &adis16485_timeouts, }, + [ADIS16490] = { + .channels = adis16485_channels, + .num_channels = ARRAY_SIZE(adis16485_channels), + .gyro_max_val = 20000 << 16, + .gyro_max_scale = IIO_DEGREE_TO_RAD(100), + .accel_max_val = IIO_M_S_2_TO_G(16000 << 16), + .accel_max_scale = 8, + .temp_scale = 14285, /* 14.285 milli degree Celsius */ + .int_clk = 4250000, + .max_dec_rate = 4250, + .filter_freqs = adis16495_def_filter_freqs, + .has_pps_clk_mode = true, + .timeouts = &adis16495_timeouts, + }, [ADIS16495_1] = { .channels = adis16485_channels, .num_channels = ARRAY_SIZE(adis16485_channels), @@ -1341,6 +1356,7 @@ static const struct spi_device_id adis16480_ids[] = { { "adis16480", ADIS16480 }, { "adis16485", ADIS16485 }, { "adis16488", ADIS16488 }, + { "adis16490", ADIS16490 }, { "adis16495-1", ADIS16495_1 }, { "adis16495-2", ADIS16495_2 }, { "adis16495-3", ADIS16495_3 }, @@ -1356,6 +1372,7 @@ static const struct of_device_id adis16480_of_match[] = { { .compatible = "adi,adis16480" }, { .compatible = "adi,adis16485" }, { .compatible = "adi,adis16488" }, + { .compatible = "adi,adis16490" }, { .compatible = "adi,adis16495-1" }, { .compatible = "adi,adis16495-2" }, { .compatible = "adi,adis16495-3" }, From 49576627b33496651d5f30ec79e164c6ba6f0410 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Thu, 16 Jan 2020 15:11:48 +0200 Subject: [PATCH 23/29] dt-bindings: iio: adis16480: add compatible entry for ADIS16490 This change adds an entry for ADIS16490 in the list of compatible devices defined in the dt-bindings of the adis16480 driver. Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/iio/imu/adi,adis16480.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/iio/imu/adi,adis16480.txt b/Documentation/devicetree/bindings/iio/imu/adi,adis16480.txt index ed7783f45233..cd903a1d880d 100644 --- a/Documentation/devicetree/bindings/iio/imu/adi,adis16480.txt +++ b/Documentation/devicetree/bindings/iio/imu/adi,adis16480.txt @@ -8,6 +8,7 @@ Required properties for the ADIS16480: * "adi,adis16480" * "adi,adis16485" * "adi,adis16488" + * "adi,adis16490" * "adi,adis16495-1" * "adi,adis16495-2" * "adi,adis16495-3" From 622b4339f93e2c2641919d405cd15e1d256f8fd3 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Mon, 13 Jan 2020 14:18:59 +0100 Subject: [PATCH 24/29] iio: adc: stm32-adc: don't print an error on probe deferral Do not print an error trace when deferring probe for some resource. Signed-off-by: Etienne Carriere Signed-off-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-adc-core.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c index 97655d7fc11a..2df88d2b880a 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -688,7 +688,8 @@ static int stm32_adc_probe(struct platform_device *pdev) priv->vref = devm_regulator_get(&pdev->dev, "vref"); if (IS_ERR(priv->vref)) { ret = PTR_ERR(priv->vref); - dev_err(&pdev->dev, "vref get failed, %d\n", ret); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "vref get failed, %d\n", ret); return ret; } @@ -696,7 +697,8 @@ static int stm32_adc_probe(struct platform_device *pdev) if (IS_ERR(priv->aclk)) { ret = PTR_ERR(priv->aclk); if (ret != -ENOENT) { - dev_err(&pdev->dev, "Can't get 'adc' clock\n"); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "Can't get 'adc' clock\n"); return ret; } priv->aclk = NULL; @@ -706,7 +708,8 @@ static int stm32_adc_probe(struct platform_device *pdev) if (IS_ERR(priv->bclk)) { ret = PTR_ERR(priv->bclk); if (ret != -ENOENT) { - dev_err(&pdev->dev, "Can't get 'bus' clock\n"); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "Can't get 'bus' clock\n"); return ret; } priv->bclk = NULL; From 04e6fedb18f6899453e59a748fb95be56ef73836 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Mon, 13 Jan 2020 11:11:40 +0100 Subject: [PATCH 25/29] iio: imu: st_lsm6dsx: add mount matrix support Allow to read the mount-matrix device tree property and provide the mount_matrix file for userspace to read. Signed-off-by: Martin Kepplinger Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 19 +++++++++++++++++++ drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 4 ++++ 2 files changed, 23 insertions(+) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index c08f57226ebb..9c3486a8134f 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -76,6 +76,7 @@ enum st_lsm6dsx_hw_id { .endianness = IIO_LE, \ }, \ .event_spec = &st_lsm6dsx_event, \ + .ext_info = st_lsm6dsx_accel_ext_info, \ .num_event_specs = 1, \ } @@ -378,6 +379,7 @@ struct st_lsm6dsx_sensor { * @enable_event: enabled event bitmask. * @iio_devs: Pointers to acc/gyro iio_dev instances. * @settings: Pointer to the specific sensor settings in use. + * @orientation: sensor chip orientation relative to main hardware. */ struct st_lsm6dsx_hw { struct device *dev; @@ -404,6 +406,8 @@ struct st_lsm6dsx_hw { struct iio_dev *iio_devs[ST_LSM6DSX_ID_MAX]; const struct st_lsm6dsx_settings *settings; + + struct iio_mount_matrix orientation; }; static __maybe_unused const struct iio_event_spec st_lsm6dsx_event = { @@ -477,4 +481,19 @@ st_lsm6dsx_write_locked(struct st_lsm6dsx_hw *hw, unsigned int addr, return err; } +static const inline struct iio_mount_matrix * +st_lsm6dsx_get_mount_matrix(const struct iio_dev *iio_dev, + const struct iio_chan_spec *chan) +{ + struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); + struct st_lsm6dsx_hw *hw = sensor->hw; + + return &hw->orientation; +} + +static const struct iio_chan_spec_ext_info st_lsm6dsx_accel_ext_info[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_lsm6dsx_get_mount_matrix), + { } +}; + #endif /* ST_LSM6DSX_H */ diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index f3ad5694437a..345fdfc89ed1 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -2337,6 +2337,10 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, return err; } + err = iio_read_mount_matrix(hw->dev, "mount-matrix", &hw->orientation); + if (err) + return err; + for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { if (!hw->iio_devs[i]) continue; From 1bde330ca0e8173d9a735a8a0a590a6e87a366cf Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 12 Jan 2020 23:33:00 +0300 Subject: [PATCH 26/29] iio: accel: kxcjk1013: Support orientation matrix Hardware could be physically mounted in any possible direction and userpspace needs to be aware of the mounting orientation in order to process sensor's data correctly. In particular this helps iio-sensor-proxy to report display's orientation properly on a phone/tablet devices. Signed-off-by: Dmitry Osipenko Acked-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/accel/kxcjk-1013.c | 27 +++++++++++++++++++++++++-- include/linux/iio/accel/kxcjk_1013.h | 3 +++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index fee535d6e45b..c9924a65c32a 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -130,6 +130,7 @@ struct kxcjk1013_data { struct i2c_client *client; struct iio_trigger *dready_trig; struct iio_trigger *motion_trig; + struct iio_mount_matrix orientation; struct mutex mutex; s16 buffer[8]; u8 odr_bits; @@ -983,6 +984,20 @@ static const struct iio_event_spec kxcjk1013_event = { BIT(IIO_EV_INFO_PERIOD) }; +static const struct iio_mount_matrix * +kxcjk1013_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct kxcjk1013_data *data = iio_priv(indio_dev); + + return &data->orientation; +} + +static const struct iio_chan_spec_ext_info kxcjk1013_ext_info[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, kxcjk1013_get_mount_matrix), + { } +}; + #define KXCJK1013_CHANNEL(_axis) { \ .type = IIO_ACCEL, \ .modified = 1, \ @@ -999,6 +1014,7 @@ static const struct iio_event_spec kxcjk1013_event = { .endianness = IIO_LE, \ }, \ .event_spec = &kxcjk1013_event, \ + .ext_info = kxcjk1013_ext_info, \ .num_event_specs = 1 \ } @@ -1267,11 +1283,18 @@ static int kxcjk1013_probe(struct i2c_client *client, data->client = client; pdata = dev_get_platdata(&client->dev); - if (pdata) + if (pdata) { data->active_high_intr = pdata->active_high_intr; - else + data->orientation = pdata->orientation; + } else { data->active_high_intr = true; /* default polarity */ + ret = iio_read_mount_matrix(&client->dev, "mount-matrix", + &data->orientation); + if (ret) + return ret; + } + if (id) { data->chipset = (enum kx_chipset)(id->driver_data); name = id->name; diff --git a/include/linux/iio/accel/kxcjk_1013.h b/include/linux/iio/accel/kxcjk_1013.h index 8c3c78bc9f91..ea0ecb774371 100644 --- a/include/linux/iio/accel/kxcjk_1013.h +++ b/include/linux/iio/accel/kxcjk_1013.h @@ -7,8 +7,11 @@ #ifndef __IIO_KXCJK_1013_H__ #define __IIO_KXCJK_1013_H__ +#include + struct kxcjk_1013_platform_data { bool active_high_intr; + struct iio_mount_matrix orientation; }; #endif From 0013ccaa136ddaa59c6fc2b2c8fbb3e865cdf8b1 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 12 Jan 2020 23:33:01 +0300 Subject: [PATCH 27/29] dt-bindings: iio: accel: kxcjk1013: Document mount-matrix property The generic IIO mount-matrix property conveys physical orientation of the hardware chip. Signed-off-by: Dmitry Osipenko Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/accel/kionix,kxcjk1013.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/accel/kionix,kxcjk1013.txt b/Documentation/devicetree/bindings/iio/accel/kionix,kxcjk1013.txt index eb76a02e2a82..ce950e162d5d 100644 --- a/Documentation/devicetree/bindings/iio/accel/kionix,kxcjk1013.txt +++ b/Documentation/devicetree/bindings/iio/accel/kionix,kxcjk1013.txt @@ -9,9 +9,16 @@ Required properties: "kionix,kxtf9" - reg: i2c slave address +Optional properties: + + - mount-matrix: an optional 3x3 mounting rotation matrix + Example: kxtf9@f { compatible = "kionix,kxtf9"; reg = <0x0F>; + mount-matrix = "0", "1", "0", + "1", "0", "0", + "0", "0", "1"; }; From 4a001c96b1c6d39831be3ef957968404be96d75e Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Mon, 13 Jan 2020 14:14:25 +0100 Subject: [PATCH 28/29] iio: dac: stm32-dac: use reset controller only at probe time This change removes the reset controller reference from the local DAC instance since it is used only at probe time. Signed-off-by: Etienne Carriere Signed-off-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/dac/stm32-dac-core.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/iio/dac/stm32-dac-core.c b/drivers/iio/dac/stm32-dac-core.c index 9e6b4cd0a5cc..4d93446c58f5 100644 --- a/drivers/iio/dac/stm32-dac-core.c +++ b/drivers/iio/dac/stm32-dac-core.c @@ -20,13 +20,11 @@ /** * struct stm32_dac_priv - stm32 DAC core private data * @pclk: peripheral clock common for all DACs - * @rst: peripheral reset control * @vref: regulator reference * @common: Common data for all DAC instances */ struct stm32_dac_priv { struct clk *pclk; - struct reset_control *rst; struct regulator *vref; struct stm32_dac_common common; }; @@ -94,6 +92,7 @@ static int stm32_dac_probe(struct platform_device *pdev) struct regmap *regmap; struct resource *res; void __iomem *mmio; + struct reset_control *rst; int ret; if (!dev->of_node) @@ -148,11 +147,11 @@ static int stm32_dac_probe(struct platform_device *pdev) priv->common.vref_mv = ret / 1000; dev_dbg(dev, "vref+=%dmV\n", priv->common.vref_mv); - priv->rst = devm_reset_control_get_exclusive(dev, NULL); - if (!IS_ERR(priv->rst)) { - reset_control_assert(priv->rst); + rst = devm_reset_control_get_exclusive(dev, NULL); + if (!IS_ERR(rst)) { + reset_control_assert(rst); udelay(2); - reset_control_deassert(priv->rst); + reset_control_deassert(rst); } if (cfg && cfg->has_hfsel) { From d344961f55fd6321937d3bc92ad3930dea31189f Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Mon, 13 Jan 2020 14:14:26 +0100 Subject: [PATCH 29/29] iio: dac: stm32-dac: better handle reset controller failures Use devm_reset_control_get_optional_exclusive() instead of devm_reset_control_get_exclusive() as reset controller is optional. Nevertheless if reset controller is expected but reports an error, propagate the error code to the caller. In such case a nice error trace is emitted unless we're deferring the probe operation. Signed-off-by: Etienne Carriere Signed-off-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/dac/stm32-dac-core.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/iio/dac/stm32-dac-core.c b/drivers/iio/dac/stm32-dac-core.c index 4d93446c58f5..7e5809ba0dee 100644 --- a/drivers/iio/dac/stm32-dac-core.c +++ b/drivers/iio/dac/stm32-dac-core.c @@ -147,8 +147,16 @@ static int stm32_dac_probe(struct platform_device *pdev) priv->common.vref_mv = ret / 1000; dev_dbg(dev, "vref+=%dmV\n", priv->common.vref_mv); - rst = devm_reset_control_get_exclusive(dev, NULL); - if (!IS_ERR(rst)) { + rst = devm_reset_control_get_optional_exclusive(dev, NULL); + if (rst) { + if (IS_ERR(rst)) { + ret = PTR_ERR(rst); + if (ret != -EPROBE_DEFER) + dev_err(dev, "reset get failed, %d\n", ret); + + goto err_hw_stop; + } + reset_control_assert(rst); udelay(2); reset_control_deassert(rst);