Add adis16501 and adis1657x support in adis16475.
Ramona Gradinariu (9):
dt-bindings: iio: imu: Add ADIS16501 compatibles
drivers: iio: imu: Add support for ADIS16501
iio: imu: adis16475: Re-define ADIS16475_DATA
iio: imu: adis_buffer: Add buffer setup API with buffer attributes
iio: imu: adis16475: Create push single sample API
drivers: iio: imu: adis16475: generic computation for sample rate
iio: imu: adis_trigger: Allow level interrupts
dt-bindings: iio: imu: Add ADIS1657X family devices compatibles
drivers: iio: imu: Add support for adis1657x family
.../bindings/iio/imu/adi,adis16475.yaml | 31 +
drivers/iio/imu/Kconfig | 4 +-
drivers/iio/imu/adis16475.c | 788 +++++++++++++++---
drivers/iio/imu/adis_buffer.c | 32 +-
drivers/iio/imu/adis_trigger.c | 39 +-
include/linux/iio/imu/adis.h | 19 +-
6 files changed, 767 insertions(+), 146 deletions(-)
--
2.34.1
Add ADIS16501 compatible. Similarly to other ADIS1650X devices,
ADIS16501 supports sync-mode values [0,2].
There are two differences between ADIS16501 and ADIS16477-2:
- ADIS16501 does not support pulse sync mode
- the delta velocity scale value is different
Acked-by: Conor Dooley <[email protected]>
Signed-off-by: Ramona Gradinariu <[email protected]>
---
no changes in v3
Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml b/Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml
index 9b7ad609f7db..db52e7063116 100644
--- a/Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml
+++ b/Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml
@@ -30,6 +30,7 @@ properties:
- adi,adis16467-2
- adi,adis16467-3
- adi,adis16500
+ - adi,adis16501
- adi,adis16505-1
- adi,adis16505-2
- adi,adis16505-3
@@ -90,6 +91,7 @@ allOf:
contains:
enum:
- adi,adis16500
+ - adi,adis16501
- adi,adis16505-1
- adi,adis16505-2
- adi,adis16505-3
--
2.34.1
Add support for ADIS16501 device in already existing ADIS16475
driver.
Signed-off-by: Ramona Gradinariu <[email protected]>
---
no changes in v3
drivers/iio/imu/Kconfig | 4 ++--
drivers/iio/imu/adis16475.c | 23 +++++++++++++++++++++++
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index 52a155ff3250..782fb80e44c2 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -36,8 +36,8 @@ config ADIS16475
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
help
Say yes here to build support for Analog Devices ADIS16470, ADIS16475,
- ADIS16477, ADIS16465, ADIS16467, ADIS16500, ADIS16505, ADIS16507 inertial
- sensors.
+ ADIS16477, ADIS16465, ADIS16467, ADIS16500, ADIS16501, ADIS16505,
+ ADIS16507 inertial sensors.
To compile this driver as a module, choose M here: the module will be
called adis16475.
diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c
index 01f55cc902fa..53872b716f4a 100644
--- a/drivers/iio/imu/adis16475.c
+++ b/drivers/iio/imu/adis16475.c
@@ -661,6 +661,7 @@ enum adis16475_variant {
ADIS16467_2,
ADIS16467_3,
ADIS16500,
+ ADIS16501,
ADIS16505_1,
ADIS16505_2,
ADIS16505_3,
@@ -980,6 +981,25 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16500, &adis1650x_timeouts),
},
+ [ADIS16501] = {
+ .name = "adis16501",
+ .num_channels = ARRAY_SIZE(adis16477_channels),
+ .channels = adis16477_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
+ .accel_max_val = 1,
+ .accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
+ .temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(720),
+ .deltvel_max_val = 125,
+ .int_clk = 2000,
+ .max_dec = 1999,
+ .sync = adis16475_sync_mode,
+ /* pulse sync not supported */
+ .num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
+ .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
+ .adis_data = ADIS16475_DATA(16501, &adis1650x_timeouts),
+ },
[ADIS16505_1] = {
.name = "adis16505-1",
.num_channels = ARRAY_SIZE(adis16477_channels),
@@ -1482,6 +1502,8 @@ static const struct of_device_id adis16475_of_match[] = {
.data = &adis16475_chip_info[ADIS16467_3] },
{ .compatible = "adi,adis16500",
.data = &adis16475_chip_info[ADIS16500] },
+ { .compatible = "adi,adis16501",
+ .data = &adis16475_chip_info[ADIS16501] },
{ .compatible = "adi,adis16505-1",
.data = &adis16475_chip_info[ADIS16505_1] },
{ .compatible = "adi,adis16505-2",
@@ -1513,6 +1535,7 @@ static const struct spi_device_id adis16475_ids[] = {
{ "adis16467-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16467_2] },
{ "adis16467-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16467_3] },
{ "adis16500", (kernel_ulong_t)&adis16475_chip_info[ADIS16500] },
+ { "adis16501", (kernel_ulong_t)&adis16475_chip_info[ADIS16501] },
{ "adis16505-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16505_1] },
{ "adis16505-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16505_2] },
{ "adis16505-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16505_3] },
--
2.34.1
Re-define ADIS16475_DATA such that it takes _burst_max_len and
_burst_max_speed_hz as parameters.
Signed-off-by: Ramona Gradinariu <[email protected]>
---
no changes in v3
drivers/iio/imu/adis16475.c | 136 +++++++++++++++++++++++-------------
1 file changed, 89 insertions(+), 47 deletions(-)
diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c
index 53872b716f4a..f9455ecb348c 100644
--- a/drivers/iio/imu/adis16475.c
+++ b/drivers/iio/imu/adis16475.c
@@ -690,32 +690,32 @@ static const char * const adis16475_status_error_msgs[] = {
[ADIS16475_DIAG_STAT_CLK] = "Clock error",
};
-#define ADIS16475_DATA(_prod_id, _timeouts) \
-{ \
- .msc_ctrl_reg = ADIS16475_REG_MSG_CTRL, \
- .glob_cmd_reg = ADIS16475_REG_GLOB_CMD, \
- .diag_stat_reg = ADIS16475_REG_DIAG_STAT, \
- .prod_id_reg = ADIS16475_REG_PROD_ID, \
- .prod_id = (_prod_id), \
- .self_test_mask = BIT(2), \
- .self_test_reg = ADIS16475_REG_GLOB_CMD, \
- .cs_change_delay = 16, \
- .read_delay = 5, \
- .write_delay = 5, \
- .status_error_msgs = adis16475_status_error_msgs, \
- .status_error_mask = BIT(ADIS16475_DIAG_STAT_DATA_PATH) | \
- BIT(ADIS16475_DIAG_STAT_FLASH_MEM) | \
- BIT(ADIS16475_DIAG_STAT_SPI) | \
- BIT(ADIS16475_DIAG_STAT_STANDBY) | \
- BIT(ADIS16475_DIAG_STAT_SENSOR) | \
- BIT(ADIS16475_DIAG_STAT_MEMORY) | \
- BIT(ADIS16475_DIAG_STAT_CLK), \
- .unmasked_drdy = true, \
- .timeouts = (_timeouts), \
- .burst_reg_cmd = ADIS16475_REG_GLOB_CMD, \
- .burst_len = ADIS16475_BURST_MAX_DATA, \
- .burst_max_len = ADIS16475_BURST32_MAX_DATA, \
- .burst_max_speed_hz = ADIS16475_BURST_MAX_SPEED \
+#define ADIS16475_DATA(_prod_id, _timeouts, _burst_max_len, _burst_max_speed_hz) \
+{ \
+ .msc_ctrl_reg = ADIS16475_REG_MSG_CTRL, \
+ .glob_cmd_reg = ADIS16475_REG_GLOB_CMD, \
+ .diag_stat_reg = ADIS16475_REG_DIAG_STAT, \
+ .prod_id_reg = ADIS16475_REG_PROD_ID, \
+ .prod_id = (_prod_id), \
+ .self_test_mask = BIT(2), \
+ .self_test_reg = ADIS16475_REG_GLOB_CMD, \
+ .cs_change_delay = 16, \
+ .read_delay = 5, \
+ .write_delay = 5, \
+ .status_error_msgs = adis16475_status_error_msgs, \
+ .status_error_mask = BIT(ADIS16475_DIAG_STAT_DATA_PATH) | \
+ BIT(ADIS16475_DIAG_STAT_FLASH_MEM) | \
+ BIT(ADIS16475_DIAG_STAT_SPI) | \
+ BIT(ADIS16475_DIAG_STAT_STANDBY) | \
+ BIT(ADIS16475_DIAG_STAT_SENSOR) | \
+ BIT(ADIS16475_DIAG_STAT_MEMORY) | \
+ BIT(ADIS16475_DIAG_STAT_CLK), \
+ .unmasked_drdy = true, \
+ .timeouts = (_timeouts), \
+ .burst_reg_cmd = ADIS16475_REG_GLOB_CMD, \
+ .burst_len = ADIS16475_BURST_MAX_DATA, \
+ .burst_max_len = _burst_max_len, \
+ .burst_max_speed_hz = _burst_max_speed_hz \
}
static const struct adis16475_sync adis16475_sync_mode[] = {
@@ -753,7 +753,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.max_dec = 1999,
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
- .adis_data = ADIS16475_DATA(16470, &adis16475_timeouts),
+ .adis_data = ADIS16475_DATA(16470, &adis16475_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16475_1] = {
.name = "adis16475-1",
@@ -770,7 +772,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.max_dec = 1999,
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
- .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts),
+ .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16475_2] = {
.name = "adis16475-2",
@@ -787,7 +791,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.max_dec = 1999,
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
- .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts),
+ .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16475_3] = {
.name = "adis16475-3",
@@ -804,7 +810,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.max_dec = 1999,
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
- .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts),
+ .adis_data = ADIS16475_DATA(16475, &adis16475_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16477_1] = {
.name = "adis16477-1",
@@ -822,7 +830,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
- .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts),
+ .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16477_2] = {
.name = "adis16477-2",
@@ -840,7 +850,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
- .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts),
+ .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16477_3] = {
.name = "adis16477-3",
@@ -858,7 +870,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
- .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts),
+ .adis_data = ADIS16475_DATA(16477, &adis16475_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16465_1] = {
.name = "adis16465-1",
@@ -875,7 +889,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.max_dec = 1999,
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
- .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts),
+ .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16465_2] = {
.name = "adis16465-2",
@@ -892,7 +908,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.max_dec = 1999,
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
- .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts),
+ .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16465_3] = {
.name = "adis16465-3",
@@ -909,7 +927,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.max_dec = 1999,
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
- .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts),
+ .adis_data = ADIS16475_DATA(16465, &adis16475_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16467_1] = {
.name = "adis16467-1",
@@ -926,7 +946,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.max_dec = 1999,
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
- .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts),
+ .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16467_2] = {
.name = "adis16467-2",
@@ -943,7 +965,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.max_dec = 1999,
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
- .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts),
+ .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16467_3] = {
.name = "adis16467-3",
@@ -960,7 +984,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.max_dec = 1999,
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
- .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts),
+ .adis_data = ADIS16475_DATA(16467, &adis16475_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16500] = {
.name = "adis16500",
@@ -979,7 +1005,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
- .adis_data = ADIS16475_DATA(16500, &adis1650x_timeouts),
+ .adis_data = ADIS16475_DATA(16500, &adis1650x_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16501] = {
.name = "adis16501",
@@ -998,7 +1026,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
- .adis_data = ADIS16475_DATA(16501, &adis1650x_timeouts),
+ .adis_data = ADIS16475_DATA(16501, &adis1650x_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16505_1] = {
.name = "adis16505-1",
@@ -1017,7 +1047,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
- .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts),
+ .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16505_2] = {
.name = "adis16505-2",
@@ -1036,7 +1068,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
- .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts),
+ .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16505_3] = {
.name = "adis16505-3",
@@ -1055,7 +1089,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
- .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts),
+ .adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16507_1] = {
.name = "adis16507-1",
@@ -1074,7 +1110,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
- .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts),
+ .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16507_2] = {
.name = "adis16507-2",
@@ -1093,7 +1131,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
- .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts),
+ .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
[ADIS16507_3] = {
.name = "adis16507-3",
@@ -1112,7 +1152,9 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
- .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts),
+ .adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts,
+ ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST_MAX_SPEED),
},
};
--
2.34.1
Create push single sample API reposnsible for pushing a single
sample into the buffer.
This is a preparation patch for FIFO support where more than
one sample has to be pushed in the trigger handler.
Signed-off-by: Ramona Gradinariu <[email protected]>
---
no changes in v3
drivers/iio/imu/adis16475.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c
index f9455ecb348c..ab955efdad92 100644
--- a/drivers/iio/imu/adis16475.c
+++ b/drivers/iio/imu/adis16475.c
@@ -1249,9 +1249,8 @@ static void adis16475_burst32_check(struct adis16475 *st)
}
}
-static irqreturn_t adis16475_trigger_handler(int irq, void *p)
+static int adis16475_push_single_sample(struct iio_poll_func *pf)
{
- struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct adis16475 *st = iio_priv(indio_dev);
struct adis *adis = &st->adis;
@@ -1340,6 +1339,15 @@ static irqreturn_t adis16475_trigger_handler(int irq, void *p)
* array.
*/
adis16475_burst32_check(st);
+ return ret;
+}
+
+static irqreturn_t adis16475_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+
+ adis16475_push_single_sample(pf);
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
--
2.34.1
Add new API called devm_adis_setup_buffer_and_trigger_with_attrs() which
also takes buffer attributes as a parameter.
Rewrite devm_adis_setup_buffer_and_trigger() implementation such that it
calls devm_adis_setup_buffer_and_trigger_with_attrs() with buffer
attributes parameter NULL
Signed-off-by: Ramona Gradinariu <[email protected]>
---
changes in v3:
- added forward declaration for iio_dev_attr
drivers/iio/imu/adis_buffer.c | 32 ++++++++++++++++++--------------
include/linux/iio/imu/adis.h | 19 +++++++++++++++----
2 files changed, 33 insertions(+), 18 deletions(-)
diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c
index 928933027ae3..871b78b225e2 100644
--- a/drivers/iio/imu/adis_buffer.c
+++ b/drivers/iio/imu/adis_buffer.c
@@ -175,31 +175,36 @@ static void adis_buffer_cleanup(void *arg)
}
/**
- * devm_adis_setup_buffer_and_trigger() - Sets up buffer and trigger for
- * the managed adis device
+ * devm_adis_setup_buffer_and_trigger_with_attrs() - Sets up buffer and trigger
+ * for the managed adis device with buffer attributes.
* @adis: The adis device
* @indio_dev: The IIO device
- * @trigger_handler: Optional trigger handler, may be NULL.
+ * @trigger_handler: Trigger handler: should handle the buffer readings.
+ * @ops: Optional buffer setup functions, may be NULL.
+ * @buffer_attrs: Extra buffer attributes.
*
* Returns 0 on success, a negative error code otherwise.
*
- * This function sets up the buffer and trigger for a adis devices. If
- * 'trigger_handler' is NULL the default trigger handler will be used. The
- * default trigger handler will simply read the registers assigned to the
- * currently active channels.
+ * This function sets up the buffer (with buffer setup functions and extra
+ * buffer attributes) and trigger for a adis devices with buffer attributes.
*/
int
-devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev,
- irq_handler_t trigger_handler)
+devm_adis_setup_buffer_and_trigger_with_attrs(struct adis *adis, struct iio_dev *indio_dev,
+ irq_handler_t trigger_handler,
+ const struct iio_buffer_setup_ops *ops,
+ const struct iio_dev_attr **buffer_attrs)
{
int ret;
if (!trigger_handler)
trigger_handler = adis_trigger_handler;
- ret = devm_iio_triggered_buffer_setup(&adis->spi->dev, indio_dev,
- &iio_pollfunc_store_time,
- trigger_handler, NULL);
+ ret = devm_iio_triggered_buffer_setup_ext(&adis->spi->dev, indio_dev,
+ &iio_pollfunc_store_time,
+ trigger_handler,
+ IIO_BUFFER_DIRECTION_IN,
+ ops,
+ buffer_attrs);
if (ret)
return ret;
@@ -212,5 +217,4 @@ devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev,
return devm_add_action_or_reset(&adis->spi->dev, adis_buffer_cleanup,
adis);
}
-EXPORT_SYMBOL_NS_GPL(devm_adis_setup_buffer_and_trigger, IIO_ADISLIB);
-
+EXPORT_SYMBOL_NS_GPL(devm_adis_setup_buffer_and_trigger_with_attrs, IIO_ADISLIB);
diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h
index 8898966bc0f0..8dda3cfa5773 100644
--- a/include/linux/iio/imu/adis.h
+++ b/include/linux/iio/imu/adis.h
@@ -21,6 +21,7 @@
#define ADIS_REG_PAGE_ID 0x00
struct adis;
+struct iio_dev_attr;
/**
* struct adis_timeouts - ADIS chip variant timeouts
@@ -515,11 +516,19 @@ int adis_single_conversion(struct iio_dev *indio_dev,
#define ADIS_ROT_CHAN(mod, addr, si, info_sep, info_all, bits) \
ADIS_MOD_CHAN(IIO_ROT, mod, addr, si, info_sep, info_all, bits)
+#define devm_adis_setup_buffer_and_trigger(adis, indio_dev, trigger_handler) \
+ devm_adis_setup_buffer_and_trigger_with_attrs((adis), (indio_dev), \
+ (trigger_handler), NULL, \
+ NULL)
+
#ifdef CONFIG_IIO_ADIS_LIB_BUFFER
int
-devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev,
- irq_handler_t trigger_handler);
+devm_adis_setup_buffer_and_trigger_with_attrs(struct adis *adis,
+ struct iio_dev *indio_dev,
+ irq_handler_t trigger_handler,
+ const struct iio_buffer_setup_ops *ops,
+ const struct iio_dev_attr **buffer_attrs);
int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev);
@@ -529,8 +538,10 @@ int adis_update_scan_mode(struct iio_dev *indio_dev,
#else /* CONFIG_IIO_BUFFER */
static inline int
-devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev,
- irq_handler_t trigger_handler)
+devm_adis_setup_buffer_and_trigger_with_attrs(struct adis *adis, struct iio_dev *indio_dev,
+ irq_handler_t trigger_handler,
+ const struct iio_buffer_setup_ops *ops,
+ const struct iio_dev_attr **buffer_attrs)
{
return 0;
}
--
2.34.1
Currently adis16475 supports a sample rate between 1900 and 2100 Hz.
This patch changes the setting of sample rate from hardcoded values to
a generic computation based on the internal clock frequency.
This is a preparatory patch for adding support for adis1657x family
devices which allow sample rates between 3900 and 4100 Hz.
Signed-off-by: Ramona Gradinariu <[email protected]>
---
no changes in v3
drivers/iio/imu/adis16475.c | 39 +++++++++++++++++++++----------------
1 file changed, 22 insertions(+), 17 deletions(-)
diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c
index ab955efdad92..c589f214259b 100644
--- a/drivers/iio/imu/adis16475.c
+++ b/drivers/iio/imu/adis16475.c
@@ -310,6 +310,9 @@ static int adis16475_set_freq(struct adis16475 *st, const u32 freq)
u16 dec;
int ret;
u32 sample_rate = st->clk_freq;
+ /* The optimal sample rate for the supported IMUs is between int_clk - 100 and int_clk + 100. */
+ u32 max_sample_rate = st->info->int_clk * 1000 + 100000;
+ u32 min_sample_rate = st->info->int_clk * 1000 - 100000;
if (!freq)
return -EINVAL;
@@ -317,8 +320,9 @@ static int adis16475_set_freq(struct adis16475 *st, const u32 freq)
adis_dev_lock(&st->adis);
/*
* When using sync scaled mode, the input clock needs to be scaled so that we have
- * an IMU sample rate between (optimally) 1900 and 2100. After this, we can use the
- * decimation filter to lower the sampling rate in order to get what the user wants.
+ * an IMU sample rate between (optimally) int_clk - 100 and int_clk + 100.
+ * After this, we can use the decimation filter to lower the sampling rate in order
+ * to get what the user wants.
* Optimally, the user sample rate is a multiple of both the IMU sample rate and
* the input clock. Hence, calculating the sync_scale dynamically gives us better
* chances of achieving a perfect/integer value for DEC_RATE. The math here is:
@@ -336,23 +340,24 @@ static int adis16475_set_freq(struct adis16475 *st, const u32 freq)
* solution. In this case, we get the highest multiple of the input clock
* lower than the IMU max sample rate.
*/
- if (scaled_rate > 2100000)
- scaled_rate = 2100000 / st->clk_freq * st->clk_freq;
+ if (scaled_rate > max_sample_rate)
+ scaled_rate = max_sample_rate / st->clk_freq * st->clk_freq;
else
- scaled_rate = 2100000 / scaled_rate * scaled_rate;
+ scaled_rate = max_sample_rate / scaled_rate * scaled_rate;
/*
* This is not an hard requirement but it's not advised to run the IMU
- * with a sample rate lower than 1900Hz due to possible undersampling
- * issues. However, there are users that might really want to take the risk.
- * Hence, we provide a module parameter for them. If set, we allow sample
- * rates lower than 1.9KHz. By default, we won't allow this and we just roundup
- * the rate to the next multiple of the input clock bigger than 1.9KHz. This
- * is done like this as in some cases (when DEC_RATE is 0) might give
- * us the closest value to the one desired by the user...
+ * with a sample rate lower than internal clock frequency, due to possible
+ * undersampling issues. However, there are users that might really want
+ * to take the risk. Hence, we provide a module parameter for them. If set,
+ * we allow sample rates lower than internal clock frequency.
+ * By default, we won't allow this and we just roundup the rate to the next
+ * multiple of the input clock. This is done like this as in some cases
+ * (when DEC_RATE is 0) might give us the closest value to the one desired
+ * by the user...
*/
- if (scaled_rate < 1900000 && !low_rate_allow)
- scaled_rate = roundup(1900000, st->clk_freq);
+ if (scaled_rate < min_sample_rate && !low_rate_allow)
+ scaled_rate = roundup(min_sample_rate, st->clk_freq);
sync_scale = scaled_rate / st->clk_freq;
ret = __adis_write_reg_16(&st->adis, ADIS16475_REG_UP_SCALE, sync_scale);
@@ -1359,6 +1364,7 @@ static int adis16475_config_sync_mode(struct adis16475 *st)
struct device *dev = &st->adis.spi->dev;
const struct adis16475_sync *sync;
u32 sync_mode;
+ u16 max_sample_rate = st->info->int_clk + 100;
/* default to internal clk */
st->clk_freq = st->info->int_clk * 1000;
@@ -1398,10 +1404,9 @@ static int adis16475_config_sync_mode(struct adis16475 *st)
/*
* In sync scaled mode, the IMU sample rate is the clk_freq * sync_scale.
* Hence, default the IMU sample rate to the highest multiple of the input
- * clock lower than the IMU max sample rate. The optimal range is
- * 1900-2100 sps...
+ * clock lower than the IMU max sample rate.
*/
- up_scale = 2100 / st->clk_freq;
+ up_scale = max_sample_rate / st->clk_freq;
ret = __adis_write_reg_16(&st->adis,
ADIS16475_REG_UP_SCALE,
--
2.34.1
Currently, adis library allows configuration only for edge interrupts,
needed for data ready sampling.
This patch removes the restriction for level interrupts, which are
needed to handle FIFO watermark interrupts.
Furthermore, in case of level interrupts, devm_request_threaded_irq is
used for interrupt allocation, to avoid blocking the processor while
retrieving the FIFO samples.
Signed-off-by: Ramona Gradinariu <[email protected]>
---
changes in v3:
- new patch
drivers/iio/imu/adis_trigger.c | 39 ++++++++++++++++++----------------
1 file changed, 21 insertions(+), 18 deletions(-)
diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c
index f890bf842db8..becf1f558b4e 100644
--- a/drivers/iio/imu/adis_trigger.c
+++ b/drivers/iio/imu/adis_trigger.c
@@ -34,21 +34,16 @@ static int adis_validate_irq_flag(struct adis *adis)
if (adis->data->unmasked_drdy)
adis->irq_flag |= IRQF_NO_AUTOEN;
/*
- * Typically this devices have data ready either on the rising edge or
- * on the falling edge of the data ready pin. This checks enforces that
- * one of those is set in the drivers... It defaults to
- * IRQF_TRIGGER_RISING for backward compatibility with devices that
- * don't support changing the pin polarity.
+ * Typically adis devices without fifo have data ready either on the
+ * rising edge or on the falling edge of the data ready pin.
+ * IMU devices with fifo support have the watermark pin level driven
+ * either high or low when the fifo is filled with the desired number
+ * of samples.
+ * It defaults to IRQF_TRIGGER_RISING for backward compatibility with
+ * devices that don't support changing the pin polarity.
*/
- if (direction == IRQF_TRIGGER_NONE) {
+ if (direction == IRQF_TRIGGER_NONE)
adis->irq_flag |= IRQF_TRIGGER_RISING;
- return 0;
- } else if (direction != IRQF_TRIGGER_RISING &&
- direction != IRQF_TRIGGER_FALLING) {
- dev_err(&adis->spi->dev, "Invalid IRQ mask: %08lx\n",
- adis->irq_flag);
- return -EINVAL;
- }
return 0;
}
@@ -77,11 +72,19 @@ int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev)
if (ret)
return ret;
- ret = devm_request_irq(&adis->spi->dev, adis->spi->irq,
- &iio_trigger_generic_data_rdy_poll,
- adis->irq_flag,
- indio_dev->name,
- adis->trig);
+ if (adis->irq_flag & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW))
+ ret = devm_request_threaded_irq(&adis->spi->dev, adis->spi->irq,
+ NULL,
+ &iio_trigger_generic_data_rdy_poll,
+ adis->irq_flag | IRQF_ONESHOT,
+ indio_dev->name,
+ adis->trig);
+ else
+ ret = devm_request_irq(&adis->spi->dev, adis->spi->irq,
+ &iio_trigger_generic_data_rdy_poll,
+ adis->irq_flag,
+ indio_dev->name,
+ adis->trig);
if (ret)
return ret;
--
2.34.1
Add support for ADIS1657X family devices in already exiting ADIS16475
driver.
Signed-off-by: Ramona Gradinariu <[email protected]>
---
changes in v3:
- changed format in sysfs_emit
- created new function adis16575_update_msg_for_burst to make it more obvious
that adis message is changing based on the given burst request value
- adjusted line wrapping for adis16475_trigger_handler_with_fifo comment
- fixed comment typo regarding watermark pin polarity
- configured level interrupts in case device has FIFO
drivers/iio/imu/adis16475.c | 628 ++++++++++++++++++++++++++++++++----
1 file changed, 561 insertions(+), 67 deletions(-)
diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c
index c589f214259b..a1a14b0757e8 100644
--- a/drivers/iio/imu/adis16475.c
+++ b/drivers/iio/imu/adis16475.c
@@ -14,6 +14,7 @@
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/imu/adis.h>
+#include <linux/iio/sysfs.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/irq.h>
#include <linux/lcm.h>
@@ -52,6 +53,8 @@
FIELD_PREP(ADIS16475_MSG_CTRL_DR_POL_MASK, x)
#define ADIS16475_SYNC_MODE_MASK GENMASK(4, 2)
#define ADIS16475_SYNC_MODE(x) FIELD_PREP(ADIS16475_SYNC_MODE_MASK, x)
+#define ADIS16575_SYNC_4KHZ_MASK BIT(11)
+#define ADIS16575_SYNC_4KHZ(x) FIELD_PREP(ADIS16575_SYNC_4KHZ_MASK, x)
#define ADIS16475_REG_UP_SCALE 0x62
#define ADIS16475_REG_DEC_RATE 0x64
#define ADIS16475_REG_GLOB_CMD 0x68
@@ -65,15 +68,32 @@
#define ADIS16500_BURST32_MASK BIT(9)
#define ADIS16500_BURST32(x) FIELD_PREP(ADIS16500_BURST32_MASK, x)
/* number of data elements in burst mode */
-#define ADIS16475_BURST32_MAX_DATA 32
+#define ADIS16475_BURST32_MAX_DATA_NO_TS32 32
+#define ADIS16575_BURST32_DATA_TS32 34
#define ADIS16475_BURST_MAX_DATA 20
#define ADIS16475_MAX_SCAN_DATA 20
/* spi max speed in brust mode */
#define ADIS16475_BURST_MAX_SPEED 1000000
+#define ADIS16575_BURST_MAX_SPEED 8000000
#define ADIS16475_LSB_DEC_MASK 0
#define ADIS16475_LSB_FIR_MASK 1
#define ADIS16500_BURST_DATA_SEL_0_CHN_MASK GENMASK(5, 0)
#define ADIS16500_BURST_DATA_SEL_1_CHN_MASK GENMASK(12, 7)
+#define ADIS16575_MAX_FIFO_WM 511UL
+#define ADIS16475_REG_FIFO_CTRL 0x5A
+#define ADIS16575_WM_LVL_MASK GENMASK(15, 4)
+#define ADIS16575_WM_LVL(x) FIELD_PREP(ADIS16575_WM_LVL_MASK, x)
+#define ADIS16575_WM_POL_MASK BIT(3)
+#define ADIS16575_WM_POL(x) FIELD_PREP(ADIS16575_WM_POL_MASK, x)
+#define ADIS16575_WM_EN_MASK BIT(2)
+#define ADIS16575_WM_EN(x) FIELD_PREP(ADIS16575_WM_EN_MASK, x)
+#define ADIS16575_OVERFLOW_MASK BIT(1)
+#define ADIS16575_STOP_ENQUEUE FIELD_PREP(ADIS16575_OVERFLOW_MASK, 0)
+#define ADIS16575_OVERWRITE_OLDEST FIELD_PREP(ADIS16575_OVERFLOW_MASK, 1)
+#define ADIS16575_FIFO_EN_MASK BIT(0)
+#define ADIS16575_FIFO_EN(x) FIELD_PREP(ADIS16575_FIFO_EN_MASK, x)
+#define ADIS16575_FIFO_FLUSH_CMD BIT(5)
+#define ADIS16575_REG_FIFO_CNT 0x3C
enum {
ADIS16475_SYNC_DIRECT = 1,
@@ -95,6 +115,9 @@ struct adis16475_chip_info {
const char *name;
#define ADIS16475_HAS_BURST32 BIT(0)
#define ADIS16475_HAS_BURST_DELTA_DATA BIT(1)
+#define ADIS16475_HAS_TIMESTAMP32 BIT(2)
+#define ADIS16475_NEEDS_BURST_REQUEST BIT(3)
+#define ADIS16475_HAS_FIFO BIT(4)
const long flags;
u32 num_channels;
u32 gyro_max_val;
@@ -116,6 +139,7 @@ struct adis16475 {
bool burst32;
unsigned long lsb_flag;
u16 sync_mode;
+ u16 fifo_watermark;
/* Alignment needed for the timestamp */
__be16 data[ADIS16475_MAX_SCAN_DATA] __aligned(8);
};
@@ -442,6 +466,124 @@ static int adis16475_set_filter(struct adis16475 *st, const u32 filter)
return 0;
}
+static ssize_t adis16475_get_fifo_enabled(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct adis16475 *st = iio_priv(indio_dev);
+ int ret;
+ u16 val;
+
+ ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FIFO_CTRL, &val);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%lu\n", FIELD_GET(ADIS16575_FIFO_EN_MASK, val));
+}
+
+static ssize_t adis16475_get_fifo_watermark(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct adis16475 *st = iio_priv(indio_dev);
+ int ret;
+ u16 val;
+
+ ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FIFO_CTRL, &val);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%lu\n", FIELD_GET(ADIS16575_WM_LVL_MASK, val) + 1);
+}
+
+static ssize_t hwfifo_watermark_min_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sysfs_emit(buf, "1\n");
+}
+
+static ssize_t hwfifo_watermark_max_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sysfs_emit(buf, "%lu\n", ADIS16575_MAX_FIFO_WM);
+}
+
+static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0);
+static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0);
+static IIO_DEVICE_ATTR(hwfifo_watermark, 0444,
+ adis16475_get_fifo_watermark, NULL, 0);
+static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,
+ adis16475_get_fifo_enabled, NULL, 0);
+
+static const struct iio_dev_attr *adis16475_fifo_attributes[] = {
+ &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr,
+ &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
+ &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
+ &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
+ NULL
+};
+
+static int adis16475_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct adis16475 *st = iio_priv(indio_dev);
+ struct adis *adis = &st->adis;
+
+ return adis_update_bits(adis, ADIS16475_REG_FIFO_CTRL,
+ ADIS16575_FIFO_EN_MASK, (u16)ADIS16575_FIFO_EN(1));
+}
+
+static int adis16475_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct adis16475 *st = iio_priv(indio_dev);
+ struct adis *adis = &st->adis;
+ int ret;
+
+ adis_dev_lock(&st->adis);
+
+ ret = __adis_update_bits(adis, ADIS16475_REG_FIFO_CTRL,
+ ADIS16575_FIFO_EN_MASK, (u16)ADIS16575_FIFO_EN(0));
+ if (ret)
+ goto unlock;
+
+ ret = __adis_write_reg_16(adis, ADIS16475_REG_GLOB_CMD,
+ ADIS16575_FIFO_FLUSH_CMD);
+
+unlock:
+ adis_dev_unlock(&st->adis);
+ return ret;
+}
+
+static const struct iio_buffer_setup_ops adis16475_buffer_ops = {
+ .postenable = adis16475_buffer_postenable,
+ .postdisable = adis16475_buffer_postdisable,
+};
+
+static int adis16475_set_watermark(struct iio_dev *indio_dev, unsigned int val)
+{
+ struct adis16475 *st = iio_priv(indio_dev);
+ int ret;
+ u16 wm_lvl;
+
+ adis_dev_lock(&st->adis);
+
+ val = min_t(unsigned int, val, ADIS16575_MAX_FIFO_WM);
+
+ wm_lvl = ADIS16575_WM_LVL(val - 1);
+ ret = __adis_update_bits(&st->adis, ADIS16475_REG_FIFO_CTRL, ADIS16575_WM_LVL_MASK, wm_lvl);
+ if (ret)
+ goto unlock;
+
+ st->fifo_watermark = val;
+
+unlock:
+ adis_dev_unlock(&st->adis);
+ return ret;
+}
+
static const u32 adis16475_calib_regs[] = {
[ADIS16475_SCAN_GYRO_X] = ADIS16475_REG_X_GYRO_BIAS_L,
[ADIS16475_SCAN_GYRO_Y] = ADIS16475_REG_Y_GYRO_BIAS_L,
@@ -673,6 +815,12 @@ enum adis16475_variant {
ADIS16507_1,
ADIS16507_2,
ADIS16507_3,
+ ADIS16575_2,
+ ADIS16575_3,
+ ADIS16576_2,
+ ADIS16576_3,
+ ADIS16577_2,
+ ADIS16577_3,
};
enum {
@@ -730,6 +878,12 @@ static const struct adis16475_sync adis16475_sync_mode[] = {
{ ADIS16475_SYNC_PULSE, 1000, 2100 },
};
+static const struct adis16475_sync adis16575_sync_mode[] = {
+ { ADIS16475_SYNC_OUTPUT },
+ { ADIS16475_SYNC_DIRECT, 1900, 4100 },
+ { ADIS16475_SYNC_SCALED, 1, 400 },
+};
+
static const struct adis_timeout adis16475_timeouts = {
.reset_ms = 200,
.sw_reset_ms = 200,
@@ -759,7 +913,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
.adis_data = ADIS16475_DATA(16470, &adis16475_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16475_1] = {
@@ -778,7 +932,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
.adis_data = ADIS16475_DATA(16475, &adis16475_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16475_2] = {
@@ -797,7 +951,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
.adis_data = ADIS16475_DATA(16475, &adis16475_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16475_3] = {
@@ -816,7 +970,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
.adis_data = ADIS16475_DATA(16475, &adis16475_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16477_1] = {
@@ -836,7 +990,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16477, &adis16475_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16477_2] = {
@@ -856,7 +1010,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16477, &adis16475_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16477_3] = {
@@ -876,7 +1030,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16477, &adis16475_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16465_1] = {
@@ -895,7 +1049,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
.adis_data = ADIS16475_DATA(16465, &adis16475_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16465_2] = {
@@ -914,7 +1068,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
.adis_data = ADIS16475_DATA(16465, &adis16475_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16465_3] = {
@@ -933,7 +1087,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
.adis_data = ADIS16475_DATA(16465, &adis16475_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16467_1] = {
@@ -952,7 +1106,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
.adis_data = ADIS16475_DATA(16467, &adis16475_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16467_2] = {
@@ -971,7 +1125,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
.adis_data = ADIS16475_DATA(16467, &adis16475_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16467_3] = {
@@ -990,7 +1144,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
.adis_data = ADIS16475_DATA(16467, &adis16475_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16500] = {
@@ -1011,7 +1165,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16500, &adis1650x_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16501] = {
@@ -1032,7 +1186,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16501, &adis1650x_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16505_1] = {
@@ -1053,7 +1207,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16505_2] = {
@@ -1074,7 +1228,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16505_3] = {
@@ -1095,7 +1249,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16507_1] = {
@@ -1116,7 +1270,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16507_2] = {
@@ -1137,7 +1291,7 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
[ADIS16507_3] = {
@@ -1158,9 +1312,153 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts,
- ADIS16475_BURST32_MAX_DATA,
+ ADIS16475_BURST32_MAX_DATA_NO_TS32,
ADIS16475_BURST_MAX_SPEED),
},
+ [ADIS16575_2] = {
+ .name = "adis16575-2",
+ .num_channels = ARRAY_SIZE(adis16477_channels),
+ .channels = adis16477_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
+ .accel_max_val = 8,
+ .accel_max_scale = IIO_M_S_2_TO_G(32000 << 16),
+ .temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(450),
+ .deltvel_max_val = 100,
+ .int_clk = 4000,
+ .max_dec = 3999,
+ .sync = adis16575_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16575_sync_mode),
+ .flags = ADIS16475_HAS_BURST32 |
+ ADIS16475_HAS_BURST_DELTA_DATA |
+ ADIS16475_NEEDS_BURST_REQUEST |
+ ADIS16475_HAS_TIMESTAMP32 |
+ ADIS16475_HAS_FIFO,
+ .adis_data = ADIS16475_DATA(16575, &adis16475_timeouts,
+ ADIS16575_BURST32_DATA_TS32,
+ ADIS16575_BURST_MAX_SPEED),
+ },
+ [ADIS16575_3] = {
+ .name = "adis16575-3",
+ .num_channels = ARRAY_SIZE(adis16477_channels),
+ .channels = adis16477_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+ .accel_max_val = 8,
+ .accel_max_scale = IIO_M_S_2_TO_G(32000 << 16),
+ .temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(2000),
+ .deltvel_max_val = 100,
+ .int_clk = 4000,
+ .max_dec = 3999,
+ .sync = adis16575_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16575_sync_mode),
+ .flags = ADIS16475_HAS_BURST32 |
+ ADIS16475_HAS_BURST_DELTA_DATA |
+ ADIS16475_NEEDS_BURST_REQUEST |
+ ADIS16475_HAS_TIMESTAMP32 |
+ ADIS16475_HAS_FIFO,
+ .adis_data = ADIS16475_DATA(16575, &adis16475_timeouts,
+ ADIS16575_BURST32_DATA_TS32,
+ ADIS16575_BURST_MAX_SPEED),
+ },
+ [ADIS16576_2] = {
+ .name = "adis16576-2",
+ .num_channels = ARRAY_SIZE(adis16477_channels),
+ .channels = adis16477_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
+ .accel_max_val = 40,
+ .accel_max_scale = IIO_M_S_2_TO_G(32000 << 16),
+ .temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(450),
+ .deltvel_max_val = 125,
+ .int_clk = 4000,
+ .max_dec = 3999,
+ .sync = adis16575_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16575_sync_mode),
+ .flags = ADIS16475_HAS_BURST32 |
+ ADIS16475_HAS_BURST_DELTA_DATA |
+ ADIS16475_NEEDS_BURST_REQUEST |
+ ADIS16475_HAS_TIMESTAMP32 |
+ ADIS16475_HAS_FIFO,
+ .adis_data = ADIS16475_DATA(16576, &adis16475_timeouts,
+ ADIS16575_BURST32_DATA_TS32,
+ ADIS16575_BURST_MAX_SPEED),
+ },
+ [ADIS16576_3] = {
+ .name = "adis16576-3",
+ .num_channels = ARRAY_SIZE(adis16477_channels),
+ .channels = adis16477_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+ .accel_max_val = 40,
+ .accel_max_scale = IIO_M_S_2_TO_G(32000 << 16),
+ .temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(2000),
+ .deltvel_max_val = 125,
+ .int_clk = 4000,
+ .max_dec = 3999,
+ .sync = adis16575_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16575_sync_mode),
+ .flags = ADIS16475_HAS_BURST32 |
+ ADIS16475_HAS_BURST_DELTA_DATA |
+ ADIS16475_NEEDS_BURST_REQUEST |
+ ADIS16475_HAS_TIMESTAMP32 |
+ ADIS16475_HAS_FIFO,
+ .adis_data = ADIS16475_DATA(16576, &adis16475_timeouts,
+ ADIS16575_BURST32_DATA_TS32,
+ ADIS16575_BURST_MAX_SPEED),
+ },
+ [ADIS16577_2] = {
+ .name = "adis16577-2",
+ .num_channels = ARRAY_SIZE(adis16477_channels),
+ .channels = adis16477_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
+ .accel_max_val = 40,
+ .accel_max_scale = IIO_M_S_2_TO_G(32000 << 16),
+ .temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(450),
+ .deltvel_max_val = 400,
+ .int_clk = 4000,
+ .max_dec = 3999,
+ .sync = adis16575_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16575_sync_mode),
+ .flags = ADIS16475_HAS_BURST32 |
+ ADIS16475_HAS_BURST_DELTA_DATA |
+ ADIS16475_NEEDS_BURST_REQUEST |
+ ADIS16475_HAS_TIMESTAMP32 |
+ ADIS16475_HAS_FIFO,
+ .adis_data = ADIS16475_DATA(16577, &adis16475_timeouts,
+ ADIS16575_BURST32_DATA_TS32,
+ ADIS16575_BURST_MAX_SPEED),
+ },
+ [ADIS16577_3] = {
+ .name = "adis16577-3",
+ .num_channels = ARRAY_SIZE(adis16477_channels),
+ .channels = adis16477_channels,
+ .gyro_max_val = 1,
+ .gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+ .accel_max_val = 40,
+ .accel_max_scale = IIO_M_S_2_TO_G(32000 << 16),
+ .temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(2000),
+ .deltvel_max_val = 400,
+ .int_clk = 4000,
+ .max_dec = 3999,
+ .sync = adis16575_sync_mode,
+ .num_sync = ARRAY_SIZE(adis16575_sync_mode),
+ .flags = ADIS16475_HAS_BURST32 |
+ ADIS16475_HAS_BURST_DELTA_DATA |
+ ADIS16475_NEEDS_BURST_REQUEST |
+ ADIS16475_HAS_TIMESTAMP32 |
+ ADIS16475_HAS_FIFO,
+ .adis_data = ADIS16475_DATA(16577, &adis16475_timeouts,
+ ADIS16575_BURST32_DATA_TS32,
+ ADIS16575_BURST_MAX_SPEED),
+ },
};
static int adis16475_update_scan_mode(struct iio_dev *indio_dev,
@@ -1195,15 +1493,19 @@ static const struct iio_info adis16475_info = {
.debugfs_reg_access = adis_debugfs_reg_access,
};
+static const struct iio_info adis16575_info = {
+ .read_raw = &adis16475_read_raw,
+ .write_raw = &adis16475_write_raw,
+ .update_scan_mode = adis16475_update_scan_mode,
+ .debugfs_reg_access = adis_debugfs_reg_access,
+ .hwfifo_set_watermark = adis16475_set_watermark,
+};
+
static bool adis16475_validate_crc(const u8 *buffer, u16 crc,
- const bool burst32)
+ u16 burst_size, u16 start_idx)
{
int i;
- /* extra 6 elements for low gyro and accel */
- const u16 sz = burst32 ? ADIS16475_BURST32_MAX_DATA :
- ADIS16475_BURST_MAX_DATA;
-
- for (i = 0; i < sz - 2; i++)
+ for (i = start_idx; i < burst_size - 2; i++)
crc -= buffer[i];
return crc == 0;
@@ -1213,10 +1515,14 @@ static void adis16475_burst32_check(struct adis16475 *st)
{
int ret;
struct adis *adis = &st->adis;
+ u8 timestamp32 = 0;
if (!(st->info->flags & ADIS16475_HAS_BURST32))
return;
+ if (st->info->flags & ADIS16475_HAS_TIMESTAMP32)
+ timestamp32 = 1;
+
if (st->lsb_flag && !st->burst32) {
const u16 en = ADIS16500_BURST32(1);
@@ -1230,9 +1536,12 @@ static void adis16475_burst32_check(struct adis16475 *st)
/*
* In 32-bit mode we need extra 2 bytes for all gyro
* and accel channels.
+ * If the device has 32-bit timestamp value we need 2 extra
+ * bytes for it.
*/
- adis->burst_extra_len = 6 * sizeof(u16);
- adis->xfer[1].len += 6 * sizeof(u16);
+ adis->burst_extra_len = (6 + timestamp32) * sizeof(u16);
+ adis->xfer[1].len += (6 + timestamp32) * sizeof(u16);
+
dev_dbg(&adis->spi->dev, "Enable burst32 mode, xfer:%d",
adis->xfer[1].len);
@@ -1248,7 +1557,7 @@ static void adis16475_burst32_check(struct adis16475 *st)
/* Remove the extra bits */
adis->burst_extra_len = 0;
- adis->xfer[1].len -= 6 * sizeof(u16);
+ adis->xfer[1].len -= (6 + timestamp32) * sizeof(u16);
dev_dbg(&adis->spi->dev, "Disable burst32 mode, xfer:%d\n",
adis->xfer[1].len);
}
@@ -1263,20 +1572,30 @@ static int adis16475_push_single_sample(struct iio_poll_func *pf)
__be16 *buffer;
u16 crc;
bool valid;
+ u8 crc_offset = 9;
+ u16 burst_size = ADIS16475_BURST_MAX_DATA;
+ u16 start_idx = (st->info->flags & ADIS16475_HAS_TIMESTAMP32) ? 2 : 0;
+
/* offset until the first element after gyro and accel */
const u8 offset = st->burst32 ? 13 : 7;
+ if (st->burst32) {
+ crc_offset = (st->info->flags & ADIS16475_HAS_TIMESTAMP32) ? 16 : 15;
+ burst_size = (st->info->flags & ADIS16475_HAS_TIMESTAMP32) ?
+ ADIS16575_BURST32_DATA_TS32 : ADIS16475_BURST32_MAX_DATA_NO_TS32;
+ }
+
ret = spi_sync(adis->spi, &adis->msg);
if (ret)
- goto check_burst32;
+ return ret;
buffer = adis->buffer;
- crc = be16_to_cpu(buffer[offset + 2]);
- valid = adis16475_validate_crc(adis->buffer, crc, st->burst32);
+ crc = be16_to_cpu(buffer[crc_offset]);
+ valid = adis16475_validate_crc(adis->buffer, crc, burst_size, start_idx);
if (!valid) {
dev_err(&adis->spi->dev, "Invalid crc\n");
- goto check_burst32;
+ return ret;
}
for_each_set_bit(bit, indio_dev->active_scan_mask,
@@ -1337,22 +1656,123 @@ static int adis16475_push_single_sample(struct iio_poll_func *pf)
}
iio_push_to_buffers_with_timestamp(indio_dev, st->data, pf->timestamp);
-check_burst32:
+
+ return 0;
+}
+
+static irqreturn_t adis16475_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct adis16475 *st = iio_priv(indio_dev);
+
+ adis16475_push_single_sample(pf);
/*
* We only check the burst mode at the end of the current capture since
* it takes a full data ready cycle for the device to update the burst
* array.
*/
adis16475_burst32_check(st);
- return ret;
+
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
}
-static irqreturn_t adis16475_trigger_handler(int irq, void *p)
+/*
+ * This function updates the first tx byte from the adis message based on the
+ * given burst request.
+ */
+static void adis16575_update_msg_for_burst(struct adis *adis, u8 burst_req)
+{
+ unsigned int burst_max_length;
+ u8 *tx;
+
+ if (adis->data->burst_max_len)
+ burst_max_length = adis->data->burst_max_len;
+ else
+ burst_max_length = adis->data->burst_len + adis->burst_extra_len;
+
+ tx = adis->buffer + burst_max_length;
+ tx[0] = ADIS_READ_REG(burst_req);
+}
+
+static int adis16575_custom_burst_read(struct iio_poll_func *pf, u8 burst_req)
+{
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct adis16475 *st = iio_priv(indio_dev);
+ struct adis *adis = &st->adis;
+
+ adis16575_update_msg_for_burst(adis, burst_req);
+
+ if (burst_req)
+ return spi_sync(adis->spi, &adis->msg);
+
+ return adis16475_push_single_sample(pf);
+}
+
+/*
+ * This handler is meant to be used for devices which support burst readings
+ * from FIFO (namely devices from adis1657x family).
+ * In order to pop the FIFO the 0x68 0x00 FIFO pop burst request has to be sent.
+ * If the previous device command was not a FIFO pop burst request, the FIFO pop
+ * burst request will simply pop the FIFO without returning valid data.
+ * For the nth consecutive burst request, thedevice will send the data popped
+ * with the (n-1)th consecutive burst request.
+ * In order to read the data which was popped previously, without popping the
+ * FIFO, the 0x00 0x00 burst request has to be sent.
+ * If after a 0x68 0x00 FIFO pop burst request, there is any other device access
+ * different from a 0x68 0x00 or a 0x00 0x00 burst request, the FIFO data popped
+ * previously will be lost.
+ */
+static irqreturn_t adis16475_trigger_handler_with_fifo(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
+ struct adis16475 *st = iio_priv(indio_dev);
+ struct adis *adis = &st->adis;
+ int ret;
+ u16 fifo_cnt, i;
- adis16475_push_single_sample(pf);
+ adis_dev_lock(&st->adis);
+
+ ret = __adis_read_reg_16(adis, ADIS16575_REG_FIFO_CNT, &fifo_cnt);
+ if (ret)
+ goto unlock;
+
+ /*
+ * If no sample is available, nothing can be read. This can happen if
+ * a the used trigger has a higher frequency than the selected sample rate.
+ */
+ if (!fifo_cnt)
+ goto unlock;
+
+ /*
+ * First burst request - FIFO pop: popped data will be returned in the
+ * next burst request.
+ */
+ ret = adis16575_custom_burst_read(pf, adis->data->burst_reg_cmd);
+ if (ret)
+ goto unlock;
+
+ for (i = 0; i < fifo_cnt - 1; i++) {
+ ret = adis16475_push_single_sample(pf);
+ if (ret)
+ goto unlock;
+ }
+
+ /* FIFO read without popping */
+ ret = adis16575_custom_burst_read(pf, 0);
+ if (ret)
+ goto unlock;
+
+unlock:
+ /*
+ * We only check the burst mode at the end of the current capture since
+ * reading data from registers will impact the FIFO reading.
+ */
+ adis16475_burst32_check(st);
+ adis_dev_unlock(&st->adis);
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
@@ -1366,6 +1786,14 @@ static int adis16475_config_sync_mode(struct adis16475 *st)
u32 sync_mode;
u16 max_sample_rate = st->info->int_clk + 100;
+ /* if available, enable 4khz internal clock */
+ if (st->info->int_clk == 4000) {
+ ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
+ ADIS16575_SYNC_4KHZ_MASK, (u16)ADIS16575_SYNC_4KHZ(1));
+ if (ret)
+ return ret;
+ }
+
/* default to internal clk */
st->clk_freq = st->info->int_clk * 1000;
@@ -1443,34 +1871,67 @@ static int adis16475_config_irq_pin(struct adis16475 *st)
u8 polarity;
struct spi_device *spi = st->adis.spi;
- /*
- * It is possible to configure the data ready polarity. Furthermore, we
- * need to update the adis struct if we want data ready as active low.
- */
irq_type = irq_get_trigger_type(spi->irq);
- if (irq_type == IRQ_TYPE_EDGE_RISING) {
- polarity = 1;
- st->adis.irq_flag = IRQF_TRIGGER_RISING;
- } else if (irq_type == IRQ_TYPE_EDGE_FALLING) {
- polarity = 0;
- st->adis.irq_flag = IRQF_TRIGGER_FALLING;
+
+ if (st->info->flags & ADIS16475_HAS_FIFO) {
+ /*
+ * It is possible to configure the fifo watermark pin polarity.
+ * Furthermore, we need to update the adis struct if we want the
+ * watermark pin active low.
+ */
+ if (irq_type == IRQ_TYPE_LEVEL_HIGH) {
+ polarity = 1;
+ st->adis.irq_flag = IRQF_TRIGGER_HIGH;
+ } else if (irq_type == IRQ_TYPE_LEVEL_LOW) {
+ polarity = 0;
+ st->adis.irq_flag = IRQF_TRIGGER_LOW;
+ } else {
+ dev_err(&spi->dev, "Invalid interrupt type 0x%x specified\n",
+ irq_type);
+ return -EINVAL;
+ }
+
+ /* Configure the watermark pin polarity. */
+ ret = adis_update_bits(&st->adis, ADIS16475_REG_FIFO_CTRL,
+ ADIS16575_WM_POL_MASK, (u16)ADIS16575_WM_POL(polarity));
+ if (ret)
+ return ret;
+
+ /* Enable watermark interrupt pin. */
+ ret = adis_update_bits(&st->adis, ADIS16475_REG_FIFO_CTRL,
+ ADIS16575_WM_EN_MASK, (u16)ADIS16575_WM_EN(1));
+ if (ret)
+ return ret;
+
} else {
- dev_err(&spi->dev, "Invalid interrupt type 0x%x specified\n",
- irq_type);
- return -EINVAL;
- }
+ /*
+ * It is possible to configure the data ready polarity. Furthermore, we
+ * need to update the adis struct if we want data ready as active low.
+ */
+ if (irq_type == IRQ_TYPE_EDGE_RISING) {
+ polarity = 1;
+ st->adis.irq_flag = IRQF_TRIGGER_RISING;
+ } else if (irq_type == IRQ_TYPE_EDGE_FALLING) {
+ polarity = 0;
+ st->adis.irq_flag = IRQF_TRIGGER_FALLING;
+ } else {
+ dev_err(&spi->dev, "Invalid interrupt type 0x%x specified\n",
+ irq_type);
+ return -EINVAL;
+ }
- val = ADIS16475_MSG_CTRL_DR_POL(polarity);
- ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
- ADIS16475_MSG_CTRL_DR_POL_MASK, val);
- if (ret)
- return ret;
- /*
- * There is a delay writing to any bits written to the MSC_CTRL
- * register. It should not be bigger than 200us, so 250 should be more
- * than enough!
- */
- usleep_range(250, 260);
+ val = ADIS16475_MSG_CTRL_DR_POL(polarity);
+ ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
+ ADIS16475_MSG_CTRL_DR_POL_MASK, val);
+ if (ret)
+ return ret;
+ /*
+ * There is a delay writing to any bits written to the MSC_CTRL
+ * register. It should not be bigger than 200us, so 250 should be more
+ * than enough!
+ */
+ usleep_range(250, 260);
+ }
return 0;
}
@@ -1499,7 +1960,10 @@ static int adis16475_probe(struct spi_device *spi)
indio_dev->name = st->info->name;
indio_dev->channels = st->info->channels;
indio_dev->num_channels = st->info->num_channels;
- indio_dev->info = &adis16475_info;
+ if (st->info->flags & ADIS16475_HAS_FIFO)
+ indio_dev->info = &adis16575_info;
+ else
+ indio_dev->info = &adis16475_info;
indio_dev->modes = INDIO_DIRECT_MODE;
ret = __adis_initial_startup(&st->adis);
@@ -1514,8 +1978,20 @@ static int adis16475_probe(struct spi_device *spi)
if (ret)
return ret;
- ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev,
- adis16475_trigger_handler);
+ if (st->info->flags & ADIS16475_HAS_FIFO) {
+ ret = devm_adis_setup_buffer_and_trigger_with_attrs(&st->adis, indio_dev,
+ adis16475_trigger_handler_with_fifo,
+ &adis16475_buffer_ops,
+ adis16475_fifo_attributes);
+ if (ret)
+ return ret;
+ /* Update overflow behavior to always overwrite the oldest sample. */
+ ret = adis_update_bits(&st->adis, ADIS16475_REG_FIFO_CTRL,
+ ADIS16575_OVERFLOW_MASK, (u16)ADIS16575_OVERWRITE_OLDEST);
+ } else {
+ ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev,
+ adis16475_trigger_handler);
+ }
if (ret)
return ret;
@@ -1571,6 +2047,18 @@ static const struct of_device_id adis16475_of_match[] = {
.data = &adis16475_chip_info[ADIS16507_2] },
{ .compatible = "adi,adis16507-3",
.data = &adis16475_chip_info[ADIS16507_3] },
+ { .compatible = "adi,adis16575-2",
+ .data = &adis16475_chip_info[ADIS16575_2] },
+ { .compatible = "adi,adis16575-3",
+ .data = &adis16475_chip_info[ADIS16575_3] },
+ { .compatible = "adi,adis16576-2",
+ .data = &adis16475_chip_info[ADIS16576_2] },
+ { .compatible = "adi,adis16576-3",
+ .data = &adis16475_chip_info[ADIS16576_3] },
+ { .compatible = "adi,adis16577-2",
+ .data = &adis16475_chip_info[ADIS16577_2] },
+ { .compatible = "adi,adis16577-3",
+ .data = &adis16475_chip_info[ADIS16577_3] },
{ },
};
MODULE_DEVICE_TABLE(of, adis16475_of_match);
@@ -1597,6 +2085,12 @@ static const struct spi_device_id adis16475_ids[] = {
{ "adis16507-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16507_1] },
{ "adis16507-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16507_2] },
{ "adis16507-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16507_3] },
+ { "adis16575-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16575_2] },
+ { "adis16575-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16575_3] },
+ { "adis16576-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16576_2] },
+ { "adis16576-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16576_3] },
+ { "adis16577-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16577_2] },
+ { "adis16577-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16577_3] },
{ }
};
MODULE_DEVICE_TABLE(spi, adis16475_ids);
--
2.34.1
Add ADIS1657X family devices compatibles and specify the according
maximum SPI baudrate.
Similarly to other ADIS1650X devices, ADIS1657X supports sync-mode
values [0,2].
Each newly added device has a different angular velocity/linear
acceleration/ delta velocity scale combination, as follows:
Accel dynamic range sensitivity:
- 262144000 LSB/g: ADIS16575
- 52428800 LSB/g: ADIS16576, ADIS16577
Gyro dynamic range sensitivity:
- 2621440 LSB/deg/sec: ADIS1575-2, ADIS1576-2, ADIS1577-2
- 655360 LSB/deg/sec: ADIS1575-3, ADIS1576-3, ADIS1577-3
Delta velocity sensitivity:
- 2^15/100 LSB/m/sec: ADIS16575
- 2^15/125 LSB/m/sec: ADIS16576
- 2^15/400 LSB/m/sec: ADIS16577
Each ADIS1657X device supports FIFO usage and a sample-rate of 4.1KHz,
meanwhile the already existing devices do not support FIFO usage and
have a maximum sample-rate of 2.1KHz.
Reviewed-by: Conor Dooley <[email protected]>
Signed-off-by: Ramona Gradinariu <[email protected]>
---
no changes in v3
.../bindings/iio/imu/adi,adis16475.yaml | 29 +++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml b/Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml
index db52e7063116..9d185f7bfdcb 100644
--- a/Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml
+++ b/Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml
@@ -37,6 +37,12 @@ properties:
- adi,adis16507-1
- adi,adis16507-2
- adi,adis16507-3
+ - adi,adis16575-2
+ - adi,adis16575-3
+ - adi,adis16576-2
+ - adi,adis16576-3
+ - adi,adis16577-2
+ - adi,adis16577-3
reg:
maxItems: 1
@@ -98,6 +104,12 @@ allOf:
- adi,adis16507-1
- adi,adis16507-2
- adi,adis16507-3
+ - adi,adis16575-2
+ - adi,adis16575-3
+ - adi,adis16576-2
+ - adi,adis16576-3
+ - adi,adis16577-2
+ - adi,adis16577-3
then:
properties:
@@ -114,6 +126,23 @@ allOf:
dependencies:
adi,sync-mode: [ clocks ]
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - adi,adis16575-2
+ - adi,adis16575-3
+ - adi,adis16576-2
+ - adi,adis16576-3
+ - adi,adis16577-2
+ - adi,adis16577-3
+
+ then:
+ properties:
+ spi-max-frequency:
+ maximum: 15000000
+
unevaluatedProperties: false
examples:
--
2.34.1
Hi Ramona,
kernel test robot noticed the following build errors:
[auto build test ERROR on jic23-iio/togreg]
[cannot apply to linus/master v6.9 next-20240517]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Ramona-Gradinariu/dt-bindings-iio-imu-Add-ADIS16501-compatibles/20240517-155051
base: https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
patch link: https://lore.kernel.org/r/20240517074750.87376-10-ramona.bolboaca13%40gmail.com
patch subject: [PATCH v3 9/9] drivers: iio: imu: Add support for adis1657x family
config: i386-allmodconfig (https://download.01.org/0day-ci/archive/20240518/[email protected]/config)
compiler: gcc-13 (Ubuntu 13.2.0-4ubuntu3) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240518/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>):
>> drivers/iio/imu/adis16475.c:523:9: error: initialization of 'const struct iio_dev_attr *' from incompatible pointer type 'struct attribute *' [-Werror=incompatible-pointer-types]
523 | &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr,
| ^
drivers/iio/imu/adis16475.c:523:9: note: (near initialization for 'adis16475_fifo_attributes[0]')
drivers/iio/imu/adis16475.c:524:9: error: initialization of 'const struct iio_dev_attr *' from incompatible pointer type 'struct attribute *' [-Werror=incompatible-pointer-types]
524 | &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
| ^
drivers/iio/imu/adis16475.c:524:9: note: (near initialization for 'adis16475_fifo_attributes[1]')
drivers/iio/imu/adis16475.c:525:9: error: initialization of 'const struct iio_dev_attr *' from incompatible pointer type 'struct attribute *' [-Werror=incompatible-pointer-types]
525 | &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
| ^
drivers/iio/imu/adis16475.c:525:9: note: (near initialization for 'adis16475_fifo_attributes[2]')
drivers/iio/imu/adis16475.c:526:9: error: initialization of 'const struct iio_dev_attr *' from incompatible pointer type 'struct attribute *' [-Werror=incompatible-pointer-types]
526 | &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
| ^
drivers/iio/imu/adis16475.c:526:9: note: (near initialization for 'adis16475_fifo_attributes[3]')
cc1: some warnings being treated as errors
vim +523 drivers/iio/imu/adis16475.c
514
515 static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0);
516 static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0);
517 static IIO_DEVICE_ATTR(hwfifo_watermark, 0444,
518 adis16475_get_fifo_watermark, NULL, 0);
519 static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,
520 adis16475_get_fifo_enabled, NULL, 0);
521
522 static const struct iio_dev_attr *adis16475_fifo_attributes[] = {
> 523 &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr,
524 &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
525 &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
526 &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
527 NULL
528 };
529
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Hi Ramona,
kernel test robot noticed the following build errors:
[auto build test ERROR on jic23-iio/togreg]
[cannot apply to linus/master v6.9 next-20240517]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Ramona-Gradinariu/dt-bindings-iio-imu-Add-ADIS16501-compatibles/20240517-155051
base: https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
patch link: https://lore.kernel.org/r/20240517074750.87376-10-ramona.bolboaca13%40gmail.com
patch subject: [PATCH v3 9/9] drivers: iio: imu: Add support for adis1657x family
config: x86_64-allyesconfig (https://download.01.org/0day-ci/archive/20240518/[email protected]/config)
compiler: clang version 18.1.5 (https://github.com/llvm/llvm-project 617a15a9eac96088ae5e9134248d8236e34b91b1)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240518/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>):
>> drivers/iio/imu/adis16475.c:523:2: error: incompatible pointer types initializing 'const struct iio_dev_attr *' with an expression of type 'struct attribute *' [-Werror,-Wincompatible-pointer-types]
523 | &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iio/imu/adis16475.c:524:2: error: incompatible pointer types initializing 'const struct iio_dev_attr *' with an expression of type 'struct attribute *' [-Werror,-Wincompatible-pointer-types]
524 | &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iio/imu/adis16475.c:525:2: error: incompatible pointer types initializing 'const struct iio_dev_attr *' with an expression of type 'struct attribute *' [-Werror,-Wincompatible-pointer-types]
525 | &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iio/imu/adis16475.c:526:2: error: incompatible pointer types initializing 'const struct iio_dev_attr *' with an expression of type 'struct attribute *' [-Werror,-Wincompatible-pointer-types]
526 | &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 errors generated.
vim +523 drivers/iio/imu/adis16475.c
514
515 static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0);
516 static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0);
517 static IIO_DEVICE_ATTR(hwfifo_watermark, 0444,
518 adis16475_get_fifo_watermark, NULL, 0);
519 static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,
520 adis16475_get_fifo_enabled, NULL, 0);
521
522 static const struct iio_dev_attr *adis16475_fifo_attributes[] = {
> 523 &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr,
524 &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
525 &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
526 &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
527 NULL
528 };
529
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
On Fri, 17 May 2024 10:47:48 +0300
Ramona Gradinariu <[email protected]> wrote:
> Currently, adis library allows configuration only for edge interrupts,
> needed for data ready sampling.
> This patch removes the restriction for level interrupts, which are
> needed to handle FIFO watermark interrupts.
> Furthermore, in case of level interrupts, devm_request_threaded_irq is
> used for interrupt allocation, to avoid blocking the processor while
> retrieving the FIFO samples.
If respinning for any other reason, I'd rewrap this as a single paragraph.
This looks fine to me, but I'd like an Ack or RB from Nuno.
Last time I poked an adis part predated the common adis library :(
>
> Signed-off-by: Ramona Gradinariu <[email protected]>
> ---
> changes in v3:
> - new patch
> drivers/iio/imu/adis_trigger.c | 39 ++++++++++++++++++----------------
> 1 file changed, 21 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c
> index f890bf842db8..becf1f558b4e 100644
> --- a/drivers/iio/imu/adis_trigger.c
> +++ b/drivers/iio/imu/adis_trigger.c
> @@ -34,21 +34,16 @@ static int adis_validate_irq_flag(struct adis *adis)
> if (adis->data->unmasked_drdy)
> adis->irq_flag |= IRQF_NO_AUTOEN;
> /*
> - * Typically this devices have data ready either on the rising edge or
> - * on the falling edge of the data ready pin. This checks enforces that
> - * one of those is set in the drivers... It defaults to
> - * IRQF_TRIGGER_RISING for backward compatibility with devices that
> - * don't support changing the pin polarity.
> + * Typically adis devices without fifo have data ready either on the
FIFO maybe as it's an acronym.
> + * rising edge or on the falling edge of the data ready pin.
> + * IMU devices with fifo support have the watermark pin level driven
> + * either high or low when the fifo is filled with the desired number
> + * of samples.
> + * It defaults to IRQF_TRIGGER_RISING for backward compatibility with
> + * devices that don't support changing the pin polarity.
> */
> - if (direction == IRQF_TRIGGER_NONE) {
> + if (direction == IRQF_TRIGGER_NONE)
> adis->irq_flag |= IRQF_TRIGGER_RISING;
> - return 0;
> - } else if (direction != IRQF_TRIGGER_RISING &&
> - direction != IRQF_TRIGGER_FALLING) {
> - dev_err(&adis->spi->dev, "Invalid IRQ mask: %08lx\n",
> - adis->irq_flag);
> - return -EINVAL;
> - }
>
> return 0;
> }
> @@ -77,11 +72,19 @@ int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev)
> if (ret)
> return ret;
>
> - ret = devm_request_irq(&adis->spi->dev, adis->spi->irq,
> - &iio_trigger_generic_data_rdy_poll,
> - adis->irq_flag,
> - indio_dev->name,
> - adis->trig);
> + if (adis->irq_flag & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW))
> + ret = devm_request_threaded_irq(&adis->spi->dev, adis->spi->irq,
> + NULL,
> + &iio_trigger_generic_data_rdy_poll,
> + adis->irq_flag | IRQF_ONESHOT,
> + indio_dev->name,
> + adis->trig);
> + else
> + ret = devm_request_irq(&adis->spi->dev, adis->spi->irq,
> + &iio_trigger_generic_data_rdy_poll,
> + adis->irq_flag,
> + indio_dev->name,
> + adis->trig);
> if (ret)
> return ret;
>
> --
> 2.34.1
>
On Sat, 18 May 2024 14:47:01 +0800
kernel test robot <[email protected]> wrote:
> Hi Ramona,
>
> kernel test robot noticed the following build errors:
>
> [auto build test ERROR on jic23-iio/togreg]
> [cannot apply to linus/master v6.9 next-20240517]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>
> url: https://github.com/intel-lab-lkp/linux/commits/Ramona-Gradinariu/dt-bindings-iio-imu-Add-ADIS16501-compatibles/20240517-155051
> base: https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
> patch link: https://lore.kernel.org/r/20240517074750.87376-10-ramona.bolboaca13%40gmail.com
> patch subject: [PATCH v3 9/9] drivers: iio: imu: Add support for adis1657x family
> config: i386-allmodconfig (https://download.01.org/0day-ci/archive/20240518/[email protected]/config)
> compiler: gcc-13 (Ubuntu 13.2.0-4ubuntu3) 13.2.0
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240518/[email protected]/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <[email protected]>
> | Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
>
> All errors (new ones prefixed by >>):
>
> >> drivers/iio/imu/adis16475.c:523:9: error: initialization of 'const struct iio_dev_attr *' from incompatible pointer type 'struct attribute *' [-Werror=incompatible-pointer-types]
> 523 | &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr,
> | ^
> drivers/iio/imu/adis16475.c:523:9: note: (near initialization for 'adis16475_fifo_attributes[0]')
> drivers/iio/imu/adis16475.c:524:9: error: initialization of 'const struct iio_dev_attr *' from incompatible pointer type 'struct attribute *' [-Werror=incompatible-pointer-types]
> 524 | &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
> | ^
> drivers/iio/imu/adis16475.c:524:9: note: (near initialization for 'adis16475_fifo_attributes[1]')
> drivers/iio/imu/adis16475.c:525:9: error: initialization of 'const struct iio_dev_attr *' from incompatible pointer type 'struct attribute *' [-Werror=incompatible-pointer-types]
> 525 | &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
> | ^
> drivers/iio/imu/adis16475.c:525:9: note: (near initialization for 'adis16475_fifo_attributes[2]')
> drivers/iio/imu/adis16475.c:526:9: error: initialization of 'const struct iio_dev_attr *' from incompatible pointer type 'struct attribute *' [-Werror=incompatible-pointer-types]
> 526 | &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
> | ^
> drivers/iio/imu/adis16475.c:526:9: note: (near initialization for 'adis16475_fifo_attributes[3]')
> cc1: some warnings being treated as errors
>
>
> vim +523 drivers/iio/imu/adis16475.c
>
> 514
> 515 static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0);
> 516 static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0);
> 517 static IIO_DEVICE_ATTR(hwfifo_watermark, 0444,
> 518 adis16475_get_fifo_watermark, NULL, 0);
> 519 static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,
> 520 adis16475_get_fifo_enabled, NULL, 0);
> 521
> 522 static const struct iio_dev_attr *adis16475_fifo_attributes[] = {
> > 523 &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr,
> 524 &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
> 525 &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
> 526 &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
> 527 NULL
> 528 };
drop the dev_attr.attr parts. This will 'work' because they are all at the start of
the containing structure, but it should be the iio_dev_attrs as in a similar
case here:
https://elixir.bootlin.com/linux/latest/source/drivers/iio/accel/adxl372.c#L1009
> 529
>
On Fri, 17 May 2024 10:47:50 +0300
Ramona Gradinariu <[email protected]> wrote:
> Add support for ADIS1657X family devices in already exiting ADIS16475
> driver.
>
> Signed-off-by: Ramona Gradinariu <[email protected]>
Whilst it's not necessarily vital to support, it I'm curious about
what happens to the hardware timestamp? I thought we had one driver
still doing hardware timestamps directly to the buffer, but I can't
find it so I guess we now deal with alignment in the few devices with
this support. The st_lsm6dsx has this sort of combining of local
and fifo timestamps for example.
As it stands I think you push the same timestamp for all scans read
from the fifo on a particular watermark interrupt? That isn't
ideal given we should definitely be able to do better than that.
> +
> +static const struct iio_dev_attr *adis16475_fifo_attributes[] = {
> + &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr,
> + &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
> + &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
> + &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
The autobuilder caught this one. Drop the dev_attr.attr.
> + NULL
> +};
> +
> +
> +static const struct iio_buffer_setup_ops adis16475_buffer_ops = {
> + .postenable = adis16475_buffer_postenable,
> + .postdisable = adis16475_buffer_postdisable,
> +};
> +
> +static int adis16475_set_watermark(struct iio_dev *indio_dev, unsigned int val)
> +{
> + struct adis16475 *st = iio_priv(indio_dev);
> + int ret;
> + u16 wm_lvl;
> +
> + adis_dev_lock(&st->adis);
As a follow up perhaps consider defining magic to use guard() for these as there are
enough users that will be simplified to make it worth the effort.
> +
> + val = min_t(unsigned int, val, ADIS16575_MAX_FIFO_WM);
> +
> + wm_lvl = ADIS16575_WM_LVL(val - 1);
> + ret = __adis_update_bits(&st->adis, ADIS16475_REG_FIFO_CTRL, ADIS16575_WM_LVL_MASK, wm_lvl);
> + if (ret)
> + goto unlock;
> +
> + st->fifo_watermark = val;
> +
> +unlock:
> + adis_dev_unlock(&st->adis);
> + return ret;
> +}
> +
> @@ -1514,8 +1978,20 @@ static int adis16475_probe(struct spi_device *spi)
> if (ret)
> return ret;
>
> - ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev,
> - adis16475_trigger_handler);
> + if (st->info->flags & ADIS16475_HAS_FIFO) {
> + ret = devm_adis_setup_buffer_and_trigger_with_attrs(&st->adis, indio_dev,
> + adis16475_trigger_handler_with_fifo,
> + &adis16475_buffer_ops,
> + adis16475_fifo_attributes);
> + if (ret)
> + return ret;
blank line here.
> + /* Update overflow behavior to always overwrite the oldest sample. */
> + ret = adis_update_bits(&st->adis, ADIS16475_REG_FIFO_CTRL,
> + ADIS16575_OVERFLOW_MASK, (u16)ADIS16575_OVERWRITE_OLDEST);
if (ret) in here.
> + } else {
> + ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev,
> + adis16475_trigger_handler);
and if (ret) in here and drop the one that follows.
otherwise we end up with odd code pattern of handling one case in this scope and not
the other two.
> + }
On Sun, 2024-05-19 at 19:57 +0100, Jonathan Cameron wrote:
> On Fri, 17 May 2024 10:47:50 +0300
> Ramona Gradinariu <[email protected]> wrote:
>
> > Add support for ADIS1657X family devices in already exiting ADIS16475
> > driver.
> >
> > Signed-off-by: Ramona Gradinariu <[email protected]>
>
> Whilst it's not necessarily vital to support, it I'm curious about
> what happens to the hardware timestamp? I thought we had one driver
> still doing hardware timestamps directly to the buffer, but I can't
> find it so I guess we now deal with alignment in the few devices with
> this support. The st_lsm6dsx has this sort of combining of local
> and fifo timestamps for example.
>
> As it stands I think you push the same timestamp for all scans read
> from the fifo on a particular watermark interrupt? That isn't
> ideal given we should definitely be able to do better than that.
>
> > +
> > +static const struct iio_dev_attr *adis16475_fifo_attributes[] = {
> > + &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr,
> > + &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
> > + &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
> > + &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
> The autobuilder caught this one. Drop the dev_attr.attr.
>
> > + NULL
> > +};
> > +
>
> > +
> > +static const struct iio_buffer_setup_ops adis16475_buffer_ops = {
> > + .postenable = adis16475_buffer_postenable,
> > + .postdisable = adis16475_buffer_postdisable,
> > +};
> > +
> > +static int adis16475_set_watermark(struct iio_dev *indio_dev, unsigned int
> > val)
> > +{
> > + struct adis16475 *st = iio_priv(indio_dev);
> > + int ret;
> > + u16 wm_lvl;
> > +
> > + adis_dev_lock(&st->adis);
>
> As a follow up perhaps consider defining magic to use guard() for these as
> there are
> enough users that will be simplified to make it worth the effort.
>
Already on my queue but if Ramona wants to step in, good. I already have plenty
to do :)
- Nuno Sá
>
On Fri, 2024-05-17 at 10:47 +0300, Ramona Gradinariu wrote:
> Currently, adis library allows configuration only for edge interrupts,
> needed for data ready sampling.
> This patch removes the restriction for level interrupts, which are
> needed to handle FIFO watermark interrupts.
> Furthermore, in case of level interrupts, devm_request_threaded_irq is
> used for interrupt allocation, to avoid blocking the processor while
> retrieving the FIFO samples.
Technically this not totally accurate (though ends up being true) as we do read
the FIFO samples in a thread already. The part that runs on the top halve should
be:
iio_trigger_generic_data_rdy_poll() -> iio_trigger_poll() -> iio_pollfunc_store_time()
and given the FIFO nature (as the interrupt keeps firing until FIFO_CNT drops
below the watermark), it seems this is enough for you to see some freezes.
Anyhow, I'd say the commit message should be a bit refactored. This also leads to
another minor detail/question (see below)
>
> Signed-off-by: Ramona Gradinariu <[email protected]>
> ---
> changes in v3:
> - new patch
> drivers/iio/imu/adis_trigger.c | 39 ++++++++++++++++++----------------
> 1 file changed, 21 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c
> index f890bf842db8..becf1f558b4e 100644
> --- a/drivers/iio/imu/adis_trigger.c
> +++ b/drivers/iio/imu/adis_trigger.c
> @@ -34,21 +34,16 @@ static int adis_validate_irq_flag(struct adis *adis)
> if (adis->data->unmasked_drdy)
> adis->irq_flag |= IRQF_NO_AUTOEN;
> /*
> - * Typically this devices have data ready either on the rising edge
> or
> - * on the falling edge of the data ready pin. This checks enforces
> that
> - * one of those is set in the drivers... It defaults to
> - * IRQF_TRIGGER_RISING for backward compatibility with devices that
> - * don't support changing the pin polarity.
> + * Typically adis devices without fifo have data ready either on the
> + * rising edge or on the falling edge of the data ready pin.
> + * IMU devices with fifo support have the watermark pin level driven
> + * either high or low when the fifo is filled with the desired number
> + * of samples.
> + * It defaults to IRQF_TRIGGER_RISING for backward compatibility with
> + * devices that don't support changing the pin polarity.
> */
> - if (direction == IRQF_TRIGGER_NONE) {
> + if (direction == IRQF_TRIGGER_NONE)
> adis->irq_flag |= IRQF_TRIGGER_RISING;
> - return 0;
> - } else if (direction != IRQF_TRIGGER_RISING &&
> - direction != IRQF_TRIGGER_FALLING) {
> - dev_err(&adis->spi->dev, "Invalid IRQ mask: %08lx\n",
> - adis->irq_flag);
> - return -EINVAL;
> - }
I guess then we should rename the function as no actual validation is being
done, right?
>
> return 0;
> }
> @@ -77,11 +72,19 @@ int devm_adis_probe_trigger(struct adis *adis, struct
> iio_dev *indio_dev)
> if (ret)
> return ret;
>
> - ret = devm_request_irq(&adis->spi->dev, adis->spi->irq,
> - &iio_trigger_generic_data_rdy_poll,
> - adis->irq_flag,
> - indio_dev->name,
> - adis->trig);
> + if (adis->irq_flag & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW))
> + ret = devm_request_threaded_irq(&adis->spi->dev, adis->spi-
> >irq,
> + NULL,
> + &iio_trigger_generic_data_rdy
> _poll,
> + adis->irq_flag |
> IRQF_ONESHOT,
> + indio_dev->name,
> + adis->trig);
So, this is not really a big deal for me but I wonder if we should actually tie
this change to the device having FIFO support (so a boolean in the adis_data
struct)? It seems to me that's the real reason for the split... With the
boolean, we could also constrain the IRQ level support for devices supporting
FIFOs. Anyhow, since this is the first supported device with a FIFO having the
boolean (while it makes sense to me) may add more overhead than needed to the
series so I'm fine with this as-is.
- Nuno Sá
>
On 5/19/24 21:57, Jonathan Cameron wrote:
> On Fri, 17 May 2024 10:47:50 +0300
> Ramona Gradinariu <[email protected]> wrote:
>
>> Add support for ADIS1657X family devices in already exiting ADIS16475
>> driver.
>>
>> Signed-off-by: Ramona Gradinariu <[email protected]>
> Whilst it's not necessarily vital to support, it I'm curious about
> what happens to the hardware timestamp? I thought we had one driver
> still doing hardware timestamps directly to the buffer, but I can't
> find it so I guess we now deal with alignment in the few devices with
> this support. The st_lsm6dsx has this sort of combining of local
> and fifo timestamps for example.
>
> As it stands I think you push the same timestamp for all scans read
> from the fifo on a particular watermark interrupt? That isn't
> ideal given we should definitely be able to do better than that.
Currently the timestamp is added when the FIFO is read, which does not
equal the sample time.
ADI IMU devices do not actually offer a hardware timestamp. The
functionality is as follows:
- for internal sync / output sync / direct external sync the burst
data returns a data counter (which increments with each sample);
- for scaled external sync the burst data returns the 'timestamp',
which contains the time associated with the last sample in each data
update relative to the most recent edge of the external clock signal.
For example, when the value in the UP_SCALE register represents a scale
factor of 20, DEC_RATE = 0, and the external SYNC rate = 100 Hz, the
following time stamp sequence results: 0LSB, 10LSB, 21LSB, 31LSB,
41LSB, 51LSB, 61LSB, 72LSB, …, 194LSB for the 20th sample, which
translates to 0us, 490us, …, 9510 us which is the time from the
previous sync edge.
We can make assumptions, and try to better estimate the timestamp,
based on the sampling frequency.
We can assume that the last sample in the FIFO was sampled when the
watermark interrupt took place, and then, based on the sample frequency
we could decrease the timestamp with the according period for each
sample.
However, I am not sure this assumption is always valid, it depends
on when the IRQ is actually handled.
I can remove the timestamp for devices which use FIFO seeing how it
does not represent the actual sample time.
>> +static const struct iio_buffer_setup_ops adis16475_buffer_ops = {
>> + .postenable = adis16475_buffer_postenable,
>> + .postdisable = adis16475_buffer_postdisable,
>> +};
>> +
>> +static int adis16475_set_watermark(struct iio_dev *indio_dev, unsigned int val)
>> +{
>> + struct adis16475 *st = iio_priv(indio_dev);
>> + int ret;
>> + u16 wm_lvl;
>> +
>> + adis_dev_lock(&st->adis);
> As a follow up perhaps consider defining magic to use guard() for these as there are
> enough users that will be simplified to make it worth the effort.
I will do this in another patch series if that is alright.
>
>> +
>> + val = min_t(unsigned int, val, ADIS16575_MAX_FIFO_WM);
>> +
>> + wm_lvl = ADIS16575_WM_LVL(val - 1);
>> + ret = __adis_update_bits(&st->adis, ADIS16475_REG_FIFO_CTRL, ADIS16575_WM_LVL_MASK, wm_lvl);
>> + if (ret)
>> + goto unlock;
>> +
>> + st->fifo_watermark = val;
>> +
>> +unlock:
>> + adis_dev_unlock(&st->adis);
>> + return ret;
>> +}
>> +