* [PATCH v3 0/9] iio: accel: bma400: Add buffer, step and activity/inactivity
@ 2022-04-11 20:31 Jagath Jog J
2022-04-11 20:31 ` [PATCH v3 1/9] iio: accel: bma400: Fix the scale min and max macro values Jagath Jog J
` (8 more replies)
0 siblings, 9 replies; 30+ messages in thread
From: Jagath Jog J @ 2022-04-11 20:31 UTC (permalink / raw)
To: dan, jic23, andy.shevchenko; +Cc: linux-iio, linux-kernel
This patch series adds trigger buffer support with data ready interrupt,
separate channel for step counter, an event for step change interrupt,
activity recognition and activity/inactivity event support.
changes since v2
1. Reordering of header includes in the separate patch.
2. Matching the IIO syntax for multiline comment.
3. Following the preference in the interrupt handler for returning.
4. Add support for activity recognition.
5. Add support for debugfs to access registers from userspace.
6. Add support for activity and inactivity events
changes since v1
1. Added comment section that describes the math for scale calculation.
2. Added separate devm_add_action_or_reset() calls to disable regulator
and to put the sensor in power down mode.
3. Remove the err_reg_disable and out, goto labels and returning directly
if error occurs.
4. Added mutex calls while putting sensor in power down.
5. Added ___cacheline_aligned for device data.
6. Ordering the header includes.
7. Handling erroneous and spurious interrupts in the interrupt handler
by returning IRQ_NONE.
8. Using dev_err_probe() instead of dev_err().
9. Configured the interrupt to open drain.
10. Using le16_to_cpu() to fix the sparse warning.
11. Checking the step change event is enabled or not.
12. Enabling the step change event will also enable the step channel.
13. Using FIELD_GET() instead of bitwise operation.
14. Removal of dead code in the _event_config().
Jagath Jog J (9):
iio: accel: bma400: Fix the scale min and max macro values
iio: accel: bma400: Reordering of header files
iio: accel: bma400: conversion to device-managed function
iio: accel: bma400: Add triggered buffer support
iio: accel: bma400: Add separate channel for step counter
iio: accel: bma400: Add step change event
iio: accel: bma400: Add activity recognition support
iio: accel: bma400: Add debugfs register access support
iio: accel: bma400: Add support for activity and inactivity events
drivers/iio/accel/Kconfig | 2 +
drivers/iio/accel/bma400.h | 49 ++-
drivers/iio/accel/bma400_core.c | 701 +++++++++++++++++++++++++++++---
drivers/iio/accel/bma400_i2c.c | 10 +-
drivers/iio/accel/bma400_spi.c | 8 +-
5 files changed, 703 insertions(+), 67 deletions(-)
--
2.17.1
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v3 1/9] iio: accel: bma400: Fix the scale min and max macro values
2022-04-11 20:31 [PATCH v3 0/9] iio: accel: bma400: Add buffer, step and activity/inactivity Jagath Jog J
@ 2022-04-11 20:31 ` Jagath Jog J
2022-04-12 8:59 ` Andy Shevchenko
2022-04-11 20:31 ` [PATCH v3 2/9] iio: accel: bma400: Reordering of header files Jagath Jog J
` (7 subsequent siblings)
8 siblings, 1 reply; 30+ messages in thread
From: Jagath Jog J @ 2022-04-11 20:31 UTC (permalink / raw)
To: dan, jic23, andy.shevchenko; +Cc: linux-iio, linux-kernel
Changing the scale macro values to match the bma400 sensitivity
for 1 LSB of all the available ranges.
Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
---
drivers/iio/accel/bma400.h | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/accel/bma400.h b/drivers/iio/accel/bma400.h
index c4c8d74155c2..5d6a1976503f 100644
--- a/drivers/iio/accel/bma400.h
+++ b/drivers/iio/accel/bma400.h
@@ -83,8 +83,27 @@
#define BMA400_ACC_ODR_MIN_WHOLE_HZ 25
#define BMA400_ACC_ODR_MIN_HZ 12
-#define BMA400_SCALE_MIN 38357
-#define BMA400_SCALE_MAX 306864
+/*
+ * BMA400_SCALE_MIN macro value represents m/s^2 for 1 LSB before
+ * converting to micro values for +-2g range.
+ *
+ * For +-2g - 1 LSB = 0.976562 milli g = 0.009576 m/s^2
+ * For +-4g - 1 LSB = 1.953125 milli g = 0.019153 m/s^2
+ * For +-16g - 1 LSB = 7.8125 milli g = 0.076614 m/s^2
+ *
+ * The raw value which is used to select the different ranges is determined
+ * by the first bit set position from the scale value, so BMA400_SCALE_MIN
+ * should be odd.
+ *
+ * Scale values for +-2g, +-4g, +-8g and +-16g is populated into bma400_scales
+ * array by left shifting BMA400_SCALE_MIN.
+ * eg:
+ * To select +-2g = 9577 << 0 = raw value to write is 0.
+ * To select +-8g = 9577 << 2 = raw value to write is 2.
+ * To select +-16g = 9577 << 3 = raw value to write is 3.
+ */
+#define BMA400_SCALE_MIN 9577
+#define BMA400_SCALE_MAX 76617
#define BMA400_NUM_REGULATORS 2
#define BMA400_VDD_REGULATOR 0
--
2.17.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 2/9] iio: accel: bma400: Reordering of header files
2022-04-11 20:31 [PATCH v3 0/9] iio: accel: bma400: Add buffer, step and activity/inactivity Jagath Jog J
2022-04-11 20:31 ` [PATCH v3 1/9] iio: accel: bma400: Fix the scale min and max macro values Jagath Jog J
@ 2022-04-11 20:31 ` Jagath Jog J
2022-04-12 9:00 ` Andy Shevchenko
2022-04-11 20:31 ` [PATCH v3 3/9] iio: accel: bma400: conversion to device-managed function Jagath Jog J
` (6 subsequent siblings)
8 siblings, 1 reply; 30+ messages in thread
From: Jagath Jog J @ 2022-04-11 20:31 UTC (permalink / raw)
To: dan, jic23, andy.shevchenko; +Cc: linux-iio, linux-kernel
Reordering of header files and removing the iio/sysfs.h since
custom attributes are not being used in the driver.
Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
---
drivers/iio/accel/bma400_core.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
index 043002fe6f63..25ad1f7339bc 100644
--- a/drivers/iio/accel/bma400_core.c
+++ b/drivers/iio/accel/bma400_core.c
@@ -13,14 +13,14 @@
#include <linux/bitops.h>
#include <linux/device.h>
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
+#include <linux/iio/iio.h>
+
#include "bma400.h"
/*
--
2.17.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 3/9] iio: accel: bma400: conversion to device-managed function
2022-04-11 20:31 [PATCH v3 0/9] iio: accel: bma400: Add buffer, step and activity/inactivity Jagath Jog J
2022-04-11 20:31 ` [PATCH v3 1/9] iio: accel: bma400: Fix the scale min and max macro values Jagath Jog J
2022-04-11 20:31 ` [PATCH v3 2/9] iio: accel: bma400: Reordering of header files Jagath Jog J
@ 2022-04-11 20:31 ` Jagath Jog J
2022-04-12 9:04 ` Andy Shevchenko
2022-04-11 20:31 ` [PATCH v3 4/9] iio: accel: bma400: Add triggered buffer support Jagath Jog J
` (5 subsequent siblings)
8 siblings, 1 reply; 30+ messages in thread
From: Jagath Jog J @ 2022-04-11 20:31 UTC (permalink / raw)
To: dan, jic23, andy.shevchenko; +Cc: linux-iio, linux-kernel
This is a conversion to device-managed by using devm_iio_device_register
inside probe function. Previously the bma400 was not put into power down
mode in some error paths in probe where it now is, but that should cause
no harm.
The dev_set_drvdata() call, bma400_remove() function and hooks in the I2C
and SPI driver struct is removed as devm_iio_device_register function is
used to automatically unregister on driver detach.
Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
---
drivers/iio/accel/bma400.h | 2 -
drivers/iio/accel/bma400_core.c | 77 ++++++++++++++++-----------------
drivers/iio/accel/bma400_i2c.c | 8 ----
drivers/iio/accel/bma400_spi.c | 6 ---
4 files changed, 38 insertions(+), 55 deletions(-)
diff --git a/drivers/iio/accel/bma400.h b/drivers/iio/accel/bma400.h
index 5d6a1976503f..8dbf85eeb005 100644
--- a/drivers/iio/accel/bma400.h
+++ b/drivers/iio/accel/bma400.h
@@ -113,6 +113,4 @@ extern const struct regmap_config bma400_regmap_config;
int bma400_probe(struct device *dev, struct regmap *regmap, const char *name);
-void bma400_remove(struct device *dev);
-
#endif
diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
index 25ad1f7339bc..07674d89d978 100644
--- a/drivers/iio/accel/bma400_core.c
+++ b/drivers/iio/accel/bma400_core.c
@@ -560,6 +560,26 @@ static void bma400_init_tables(void)
}
}
+static void bma400_regulators_disable(void *data_ptr)
+{
+ struct bma400_data *data = data_ptr;
+
+ regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators);
+}
+
+static void bma400_power_disable(void *data_ptr)
+{
+ struct bma400_data *data = data_ptr;
+ int ret;
+
+ mutex_lock(&data->mutex);
+ ret = bma400_set_power_mode(data, POWER_MODE_SLEEP);
+ mutex_unlock(&data->mutex);
+ if (ret)
+ dev_warn(data->dev, "Failed to put device into sleep mode (%pe)\n",
+ ERR_PTR(ret));
+}
+
static int bma400_init(struct bma400_data *data)
{
unsigned int val;
@@ -569,13 +589,12 @@ static int bma400_init(struct bma400_data *data)
ret = regmap_read(data->regmap, BMA400_CHIP_ID_REG, &val);
if (ret) {
dev_err(data->dev, "Failed to read chip id register\n");
- goto out;
+ return ret;
}
if (val != BMA400_ID_REG_VAL) {
dev_err(data->dev, "Chip ID mismatch\n");
- ret = -ENODEV;
- goto out;
+ return -ENODEV;
}
data->regulators[BMA400_VDD_REGULATOR].supply = "vdd";
@@ -589,27 +608,31 @@ static int bma400_init(struct bma400_data *data)
"Failed to get regulators: %d\n",
ret);
- goto out;
+ return ret;
}
ret = regulator_bulk_enable(ARRAY_SIZE(data->regulators),
data->regulators);
if (ret) {
dev_err(data->dev, "Failed to enable regulators: %d\n",
ret);
- goto out;
+ return ret;
}
+ ret = devm_add_action_or_reset(data->dev, bma400_regulators_disable, data);
+ if (ret)
+ return ret;
+
ret = bma400_get_power_mode(data);
if (ret) {
dev_err(data->dev, "Failed to get the initial power-mode\n");
- goto err_reg_disable;
+ return ret;
}
if (data->power_mode != POWER_MODE_NORMAL) {
ret = bma400_set_power_mode(data, POWER_MODE_NORMAL);
if (ret) {
dev_err(data->dev, "Failed to wake up the device\n");
- goto err_reg_disable;
+ return ret;
}
/*
* TODO: The datasheet waits 1500us here in the example, but
@@ -618,19 +641,23 @@ static int bma400_init(struct bma400_data *data)
usleep_range(1500, 2000);
}
+ ret = devm_add_action_or_reset(data->dev, bma400_power_disable, data);
+ if (ret)
+ return ret;
+
bma400_init_tables();
ret = bma400_get_accel_output_data_rate(data);
if (ret)
- goto err_reg_disable;
+ return ret;
ret = bma400_get_accel_oversampling_ratio(data);
if (ret)
- goto err_reg_disable;
+ return ret;
ret = bma400_get_accel_scale(data);
if (ret)
- goto err_reg_disable;
+ return ret;
/*
* Once the interrupt engine is supported we might use the
@@ -639,12 +666,6 @@ static int bma400_init(struct bma400_data *data)
* channel.
*/
return regmap_write(data->regmap, BMA400_ACC_CONFIG2_REG, 0x00);
-
-err_reg_disable:
- regulator_bulk_disable(ARRAY_SIZE(data->regulators),
- data->regulators);
-out:
- return ret;
}
static int bma400_read_raw(struct iio_dev *indio_dev,
@@ -822,32 +843,10 @@ int bma400_probe(struct device *dev, struct regmap *regmap, const char *name)
indio_dev->num_channels = ARRAY_SIZE(bma400_channels);
indio_dev->modes = INDIO_DIRECT_MODE;
- dev_set_drvdata(dev, indio_dev);
-
- return iio_device_register(indio_dev);
+ return devm_iio_device_register(dev, indio_dev);
}
EXPORT_SYMBOL_NS(bma400_probe, IIO_BMA400);
-void bma400_remove(struct device *dev)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct bma400_data *data = iio_priv(indio_dev);
- int ret;
-
- mutex_lock(&data->mutex);
- ret = bma400_set_power_mode(data, POWER_MODE_SLEEP);
- mutex_unlock(&data->mutex);
-
- if (ret)
- dev_warn(dev, "Failed to put device into sleep mode (%pe)\n", ERR_PTR(ret));
-
- regulator_bulk_disable(ARRAY_SIZE(data->regulators),
- data->regulators);
-
- iio_device_unregister(indio_dev);
-}
-EXPORT_SYMBOL_NS(bma400_remove, IIO_BMA400);
-
MODULE_AUTHOR("Dan Robertson <dan@dlrobertson.com>");
MODULE_DESCRIPTION("Bosch BMA400 triaxial acceleration sensor core");
MODULE_LICENSE("GPL");
diff --git a/drivers/iio/accel/bma400_i2c.c b/drivers/iio/accel/bma400_i2c.c
index da104ffd3fe0..4f6e01a3b3a1 100644
--- a/drivers/iio/accel/bma400_i2c.c
+++ b/drivers/iio/accel/bma400_i2c.c
@@ -27,13 +27,6 @@ static int bma400_i2c_probe(struct i2c_client *client,
return bma400_probe(&client->dev, regmap, id->name);
}
-static int bma400_i2c_remove(struct i2c_client *client)
-{
- bma400_remove(&client->dev);
-
- return 0;
-}
-
static const struct i2c_device_id bma400_i2c_ids[] = {
{ "bma400", 0 },
{ }
@@ -52,7 +45,6 @@ static struct i2c_driver bma400_i2c_driver = {
.of_match_table = bma400_of_i2c_match,
},
.probe = bma400_i2c_probe,
- .remove = bma400_i2c_remove,
.id_table = bma400_i2c_ids,
};
diff --git a/drivers/iio/accel/bma400_spi.c b/drivers/iio/accel/bma400_spi.c
index 51f23bdc0ea5..28e240400a3f 100644
--- a/drivers/iio/accel/bma400_spi.c
+++ b/drivers/iio/accel/bma400_spi.c
@@ -87,11 +87,6 @@ static int bma400_spi_probe(struct spi_device *spi)
return bma400_probe(&spi->dev, regmap, id->name);
}
-static void bma400_spi_remove(struct spi_device *spi)
-{
- bma400_remove(&spi->dev);
-}
-
static const struct spi_device_id bma400_spi_ids[] = {
{ "bma400", 0 },
{ }
@@ -110,7 +105,6 @@ static struct spi_driver bma400_spi_driver = {
.of_match_table = bma400_of_spi_match,
},
.probe = bma400_spi_probe,
- .remove = bma400_spi_remove,
.id_table = bma400_spi_ids,
};
--
2.17.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 4/9] iio: accel: bma400: Add triggered buffer support
2022-04-11 20:31 [PATCH v3 0/9] iio: accel: bma400: Add buffer, step and activity/inactivity Jagath Jog J
` (2 preceding siblings ...)
2022-04-11 20:31 ` [PATCH v3 3/9] iio: accel: bma400: conversion to device-managed function Jagath Jog J
@ 2022-04-11 20:31 ` Jagath Jog J
2022-04-12 9:12 ` Andy Shevchenko
2022-04-16 16:38 ` Jonathan Cameron
2022-04-11 20:31 ` [PATCH v3 5/9] iio: accel: bma400: Add separate channel for step counter Jagath Jog J
` (4 subsequent siblings)
8 siblings, 2 replies; 30+ messages in thread
From: Jagath Jog J @ 2022-04-11 20:31 UTC (permalink / raw)
To: dan, jic23, andy.shevchenko; +Cc: linux-iio, linux-kernel
Added trigger buffer support to read continuous acceleration
data from device with data ready interrupt which is mapped
to INT1 pin.
Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
---
drivers/iio/accel/Kconfig | 2 +
drivers/iio/accel/bma400.h | 10 ++-
drivers/iio/accel/bma400_core.c | 153 ++++++++++++++++++++++++++++++--
drivers/iio/accel/bma400_i2c.c | 2 +-
drivers/iio/accel/bma400_spi.c | 2 +-
5 files changed, 161 insertions(+), 8 deletions(-)
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index eac3f02662ae..958097814232 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -204,6 +204,8 @@ config BMA220
config BMA400
tristate "Bosch BMA400 3-Axis Accelerometer Driver"
select REGMAP
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
select BMA400_I2C if I2C
select BMA400_SPI if SPI
help
diff --git a/drivers/iio/accel/bma400.h b/drivers/iio/accel/bma400.h
index 8dbf85eeb005..a7482a66b36b 100644
--- a/drivers/iio/accel/bma400.h
+++ b/drivers/iio/accel/bma400.h
@@ -62,6 +62,13 @@
#define BMA400_ACC_CONFIG2_REG 0x1b
#define BMA400_CMD_REG 0x7e
+/* Interrupt registers */
+#define BMA400_INT_CONFIG0_REG 0x1f
+#define BMA400_INT_CONFIG1_REG 0x20
+#define BMA400_INT1_MAP_REG 0x21
+#define BMA400_INT_IO_CTRL_REG 0x24
+#define BMA400_INT_DRDY_MSK BIT(7)
+
/* Chip ID of BMA 400 devices found in the chip ID register. */
#define BMA400_ID_REG_VAL 0x90
@@ -111,6 +118,7 @@
extern const struct regmap_config bma400_regmap_config;
-int bma400_probe(struct device *dev, struct regmap *regmap, const char *name);
+int bma400_probe(struct device *dev, struct regmap *regmap, int irq,
+ const char *name);
#endif
diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
index 07674d89d978..b7b2b67aef31 100644
--- a/drivers/iio/accel/bma400_core.c
+++ b/drivers/iio/accel/bma400_core.c
@@ -11,6 +11,7 @@
* - Create channel for sensor time
*/
+#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/kernel.h>
@@ -20,6 +21,10 @@
#include <linux/regulator/consumer.h>
#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
#include "bma400.h"
@@ -61,6 +66,13 @@ struct bma400_data {
struct bma400_sample_freq sample_freq;
int oversampling_ratio;
int scale;
+ struct iio_trigger *trig;
+ /* Correct time stamp alignment */
+ struct {
+ __le16 buff[3];
+ u8 temperature;
+ s64 ts __aligned(8);
+ } buffer ____cacheline_aligned;
};
static bool bma400_is_writable_reg(struct device *dev, unsigned int reg)
@@ -152,7 +164,7 @@ static const struct iio_chan_spec_ext_info bma400_ext_info[] = {
{ }
};
-#define BMA400_ACC_CHANNEL(_axis) { \
+#define BMA400_ACC_CHANNEL(_index, _axis) { \
.type = IIO_ACCEL, \
.modified = 1, \
.channel2 = IIO_MOD_##_axis, \
@@ -164,17 +176,32 @@ static const struct iio_chan_spec_ext_info bma400_ext_info[] = {
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
.ext_info = bma400_ext_info, \
+ .scan_index = _index, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 12, \
+ .storagebits = 16, \
+ .endianness = IIO_LE, \
+ }, \
}
static const struct iio_chan_spec bma400_channels[] = {
- BMA400_ACC_CHANNEL(X),
- BMA400_ACC_CHANNEL(Y),
- BMA400_ACC_CHANNEL(Z),
+ BMA400_ACC_CHANNEL(0, X),
+ BMA400_ACC_CHANNEL(1, Y),
+ BMA400_ACC_CHANNEL(2, Z),
{
.type = IIO_TEMP,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .scan_index = 3,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 8,
+ .storagebits = 8,
+ .endianness = IIO_LE,
+ },
},
+ IIO_CHAN_SOFT_TIMESTAMP(4),
};
static int bma400_get_temp_reg(struct bma400_data *data, int *val, int *val2)
@@ -659,6 +686,10 @@ static int bma400_init(struct bma400_data *data)
if (ret)
return ret;
+ /* Configure INT1 pin to open drain */
+ ret = regmap_write(data->regmap, BMA400_INT_IO_CTRL_REG, 0x06);
+ if (ret)
+ return ret;
/*
* Once the interrupt engine is supported we might use the
* data_src_reg, but for now ensure this is set to the
@@ -807,6 +838,29 @@ static int bma400_write_raw_get_fmt(struct iio_dev *indio_dev,
}
}
+static int bma400_data_rdy_trigger_set_state(struct iio_trigger *trig,
+ bool state)
+{
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct bma400_data *data = iio_priv(indio_dev);
+ int ret;
+
+ ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG0_REG,
+ BMA400_INT_DRDY_MSK,
+ FIELD_PREP(BMA400_INT_DRDY_MSK, state));
+ if (ret)
+ return ret;
+
+ return regmap_update_bits(data->regmap, BMA400_INT1_MAP_REG,
+ BMA400_INT_DRDY_MSK,
+ FIELD_PREP(BMA400_INT_DRDY_MSK, state));
+}
+
+static const unsigned long bma400_avail_scan_masks[] = {
+ GENMASK(3, 0),
+ 0
+};
+
static const struct iio_info bma400_info = {
.read_raw = bma400_read_raw,
.read_avail = bma400_read_avail,
@@ -814,7 +868,64 @@ static const struct iio_info bma400_info = {
.write_raw_get_fmt = bma400_write_raw_get_fmt,
};
-int bma400_probe(struct device *dev, struct regmap *regmap, const char *name)
+static const struct iio_trigger_ops bma400_trigger_ops = {
+ .set_trigger_state = &bma400_data_rdy_trigger_set_state,
+ .validate_device = &iio_trigger_validate_own_device,
+};
+
+static irqreturn_t bma400_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct bma400_data *data = iio_priv(indio_dev);
+ int ret, temp;
+
+ mutex_lock(&data->mutex);
+
+ /* bulk read six registers, with the base being the LSB register */
+ ret = regmap_bulk_read(data->regmap, BMA400_X_AXIS_LSB_REG,
+ &data->buffer.buff, sizeof(data->buffer.buff));
+ mutex_unlock(&data->mutex);
+ if (ret)
+ return IRQ_NONE;
+
+ ret = regmap_read(data->regmap, BMA400_TEMP_DATA_REG, &temp);
+ if (ret)
+ return IRQ_NONE;
+
+ data->buffer.temperature = temp;
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer,
+ iio_get_time_ns(indio_dev));
+
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t bma400_interrupt(int irq, void *private)
+{
+ struct iio_dev *indio_dev = private;
+ struct bma400_data *data = iio_priv(indio_dev);
+ int ret;
+ __le16 status;
+
+ mutex_lock(&data->mutex);
+ ret = regmap_bulk_read(data->regmap, BMA400_INT_STAT0_REG, &status,
+ sizeof(status));
+ mutex_unlock(&data->mutex);
+ if (ret)
+ return IRQ_NONE;
+
+ if (FIELD_GET(BMA400_INT_DRDY_MSK, le16_to_cpu(status))) {
+ iio_trigger_poll_chained(data->trig);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+int bma400_probe(struct device *dev, struct regmap *regmap, int irq,
+ const char *name)
{
struct iio_dev *indio_dev;
struct bma400_data *data;
@@ -841,8 +952,40 @@ int bma400_probe(struct device *dev, struct regmap *regmap, const char *name)
indio_dev->info = &bma400_info;
indio_dev->channels = bma400_channels;
indio_dev->num_channels = ARRAY_SIZE(bma400_channels);
+ indio_dev->available_scan_masks = bma400_avail_scan_masks;
indio_dev->modes = INDIO_DIRECT_MODE;
+ if (irq > 0) {
+ data->trig = devm_iio_trigger_alloc(dev, "%s-dev%d",
+ indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!data->trig)
+ return -ENOMEM;
+
+ data->trig->ops = &bma400_trigger_ops;
+ iio_trigger_set_drvdata(data->trig, indio_dev);
+
+ ret = devm_iio_trigger_register(data->dev, data->trig);
+ if (ret)
+ return dev_err_probe(data->dev, ret,
+ "iio trigger register fail\n");
+
+ indio_dev->trig = iio_trigger_get(data->trig);
+ ret = devm_request_threaded_irq(dev, irq, NULL,
+ &bma400_interrupt,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ indio_dev->name, indio_dev);
+ if (ret)
+ return dev_err_probe(data->dev, ret,
+ "request irq %d failed\n", irq);
+ }
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
+ &bma400_trigger_handler, NULL);
+ if (ret)
+ return dev_err_probe(data->dev, ret,
+ "iio triggered buffer setup failed\n");
+
return devm_iio_device_register(dev, indio_dev);
}
EXPORT_SYMBOL_NS(bma400_probe, IIO_BMA400);
diff --git a/drivers/iio/accel/bma400_i2c.c b/drivers/iio/accel/bma400_i2c.c
index 4f6e01a3b3a1..1ba2a982ea73 100644
--- a/drivers/iio/accel/bma400_i2c.c
+++ b/drivers/iio/accel/bma400_i2c.c
@@ -24,7 +24,7 @@ static int bma400_i2c_probe(struct i2c_client *client,
return PTR_ERR(regmap);
}
- return bma400_probe(&client->dev, regmap, id->name);
+ return bma400_probe(&client->dev, regmap, client->irq, id->name);
}
static const struct i2c_device_id bma400_i2c_ids[] = {
diff --git a/drivers/iio/accel/bma400_spi.c b/drivers/iio/accel/bma400_spi.c
index 28e240400a3f..ec13c044b304 100644
--- a/drivers/iio/accel/bma400_spi.c
+++ b/drivers/iio/accel/bma400_spi.c
@@ -84,7 +84,7 @@ static int bma400_spi_probe(struct spi_device *spi)
if (ret)
dev_err(&spi->dev, "Failed to read chip id register\n");
- return bma400_probe(&spi->dev, regmap, id->name);
+ return bma400_probe(&spi->dev, regmap, spi->irq, id->name);
}
static const struct spi_device_id bma400_spi_ids[] = {
--
2.17.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 5/9] iio: accel: bma400: Add separate channel for step counter
2022-04-11 20:31 [PATCH v3 0/9] iio: accel: bma400: Add buffer, step and activity/inactivity Jagath Jog J
` (3 preceding siblings ...)
2022-04-11 20:31 ` [PATCH v3 4/9] iio: accel: bma400: Add triggered buffer support Jagath Jog J
@ 2022-04-11 20:31 ` Jagath Jog J
2022-04-16 16:41 ` Jonathan Cameron
2022-04-11 20:31 ` [PATCH v3 6/9] iio: accel: bma400: Add step change event Jagath Jog J
` (3 subsequent siblings)
8 siblings, 1 reply; 30+ messages in thread
From: Jagath Jog J @ 2022-04-11 20:31 UTC (permalink / raw)
To: dan, jic23, andy.shevchenko; +Cc: linux-iio, linux-kernel
Added channel for step counter which can be enable or disable
through the sysfs interface.
Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
---
drivers/iio/accel/bma400.h | 1 +
drivers/iio/accel/bma400_core.c | 48 ++++++++++++++++++++++++++++++---
2 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/drivers/iio/accel/bma400.h b/drivers/iio/accel/bma400.h
index a7482a66b36b..52f9ea95de81 100644
--- a/drivers/iio/accel/bma400.h
+++ b/drivers/iio/accel/bma400.h
@@ -53,6 +53,7 @@
#define BMA400_STEP_CNT1_REG 0x16
#define BMA400_STEP_CNT3_REG 0x17
#define BMA400_STEP_STAT_REG 0x18
+#define BMA400_STEP_INT_MSK BIT(0)
/*
* Read-write configuration registers
diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
index b7b2b67aef31..c8f147163d3c 100644
--- a/drivers/iio/accel/bma400_core.c
+++ b/drivers/iio/accel/bma400_core.c
@@ -20,6 +20,8 @@
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
+#include <asm/unaligned.h>
+
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger.h>
@@ -67,6 +69,7 @@ struct bma400_data {
int oversampling_ratio;
int scale;
struct iio_trigger *trig;
+ int steps_enabled;
/* Correct time stamp alignment */
struct {
__le16 buff[3];
@@ -201,6 +204,12 @@ static const struct iio_chan_spec bma400_channels[] = {
.endianness = IIO_LE,
},
},
+ {
+ .type = IIO_STEPS,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_ENABLE),
+ .scan_index = -1, /* No buffer support */
+ },
IIO_CHAN_SOFT_TIMESTAMP(4),
};
@@ -705,13 +714,28 @@ static int bma400_read_raw(struct iio_dev *indio_dev,
{
struct bma400_data *data = iio_priv(indio_dev);
int ret;
+ u8 steps_raw[3];
switch (mask) {
case IIO_CHAN_INFO_PROCESSED:
- mutex_lock(&data->mutex);
- ret = bma400_get_temp_reg(data, val, val2);
- mutex_unlock(&data->mutex);
- return ret;
+ switch (chan->type) {
+ case IIO_TEMP:
+ mutex_lock(&data->mutex);
+ ret = bma400_get_temp_reg(data, val, val2);
+ mutex_unlock(&data->mutex);
+ return ret;
+ case IIO_STEPS:
+ mutex_lock(&data->mutex);
+ ret = regmap_bulk_read(data->regmap, BMA400_STEP_CNT0_REG,
+ &steps_raw, sizeof(steps_raw));
+ mutex_unlock(&data->mutex);
+ if (ret)
+ return ret;
+ *val = get_unaligned_le24(steps_raw);
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
case IIO_CHAN_INFO_RAW:
mutex_lock(&data->mutex);
ret = bma400_get_accel_reg(data, chan, val);
@@ -752,6 +776,9 @@ static int bma400_read_raw(struct iio_dev *indio_dev,
*val = data->oversampling_ratio;
return IIO_VAL_INT;
+ case IIO_CHAN_INFO_ENABLE:
+ *val = data->steps_enabled;
+ return IIO_VAL_INT;
default:
return -EINVAL;
}
@@ -817,6 +844,17 @@ static int bma400_write_raw(struct iio_dev *indio_dev,
ret = bma400_set_accel_oversampling_ratio(data, val);
mutex_unlock(&data->mutex);
return ret;
+ case IIO_CHAN_INFO_ENABLE:
+ if (data->steps_enabled == val)
+ return 0;
+
+ mutex_lock(&data->mutex);
+ ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG1_REG,
+ BMA400_STEP_INT_MSK,
+ FIELD_PREP(BMA400_STEP_INT_MSK, !!val));
+ mutex_unlock(&data->mutex);
+ data->steps_enabled = val;
+ return ret;
default:
return -EINVAL;
}
@@ -833,6 +871,8 @@ static int bma400_write_raw_get_fmt(struct iio_dev *indio_dev,
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
return IIO_VAL_INT;
+ case IIO_CHAN_INFO_ENABLE:
+ return IIO_VAL_INT;
default:
return -EINVAL;
}
--
2.17.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 6/9] iio: accel: bma400: Add step change event
2022-04-11 20:31 [PATCH v3 0/9] iio: accel: bma400: Add buffer, step and activity/inactivity Jagath Jog J
` (4 preceding siblings ...)
2022-04-11 20:31 ` [PATCH v3 5/9] iio: accel: bma400: Add separate channel for step counter Jagath Jog J
@ 2022-04-11 20:31 ` Jagath Jog J
2022-04-11 20:31 ` [PATCH v3 7/9] iio: accel: bma400: Add activity recognition support Jagath Jog J
` (2 subsequent siblings)
8 siblings, 0 replies; 30+ messages in thread
From: Jagath Jog J @ 2022-04-11 20:31 UTC (permalink / raw)
To: dan, jic23, andy.shevchenko; +Cc: linux-iio, linux-kernel
Added support for event when there is a detection of step change.
INT1 pin is used to interrupt and event is pushed to userspace.
Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
---
drivers/iio/accel/bma400.h | 2 +
drivers/iio/accel/bma400_core.c | 76 +++++++++++++++++++++++++++++++++
2 files changed, 78 insertions(+)
diff --git a/drivers/iio/accel/bma400.h b/drivers/iio/accel/bma400.h
index 52f9ea95de81..bc4641279be3 100644
--- a/drivers/iio/accel/bma400.h
+++ b/drivers/iio/accel/bma400.h
@@ -39,6 +39,7 @@
#define BMA400_INT_STAT0_REG 0x0e
#define BMA400_INT_STAT1_REG 0x0f
#define BMA400_INT_STAT2_REG 0x10
+#define BMA400_INT12_MAP_REG 0x23
/* Temperature register */
#define BMA400_TEMP_DATA_REG 0x11
@@ -54,6 +55,7 @@
#define BMA400_STEP_CNT3_REG 0x17
#define BMA400_STEP_STAT_REG 0x18
#define BMA400_STEP_INT_MSK BIT(0)
+#define BMA400_STEP_STAT_MASK GENMASK(9, 8)
/*
* Read-write configuration registers
diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
index c8f147163d3c..37f38626a9aa 100644
--- a/drivers/iio/accel/bma400_core.c
+++ b/drivers/iio/accel/bma400_core.c
@@ -24,6 +24,7 @@
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
+#include <linux/iio/events.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
@@ -70,6 +71,7 @@ struct bma400_data {
int scale;
struct iio_trigger *trig;
int steps_enabled;
+ bool step_event_en;
/* Correct time stamp alignment */
struct {
__le16 buff[3];
@@ -167,6 +169,12 @@ static const struct iio_chan_spec_ext_info bma400_ext_info[] = {
{ }
};
+static const struct iio_event_spec bma400_step_detect_event = {
+ .type = IIO_EV_TYPE_CHANGE,
+ .dir = IIO_EV_DIR_NONE,
+ .mask_separate = BIT(IIO_EV_INFO_ENABLE),
+};
+
#define BMA400_ACC_CHANNEL(_index, _axis) { \
.type = IIO_ACCEL, \
.modified = 1, \
@@ -209,6 +217,8 @@ static const struct iio_chan_spec bma400_channels[] = {
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
BIT(IIO_CHAN_INFO_ENABLE),
.scan_index = -1, /* No buffer support */
+ .event_spec = &bma400_step_detect_event,
+ .num_event_specs = 1,
},
IIO_CHAN_SOFT_TIMESTAMP(4),
};
@@ -878,6 +888,60 @@ static int bma400_write_raw_get_fmt(struct iio_dev *indio_dev,
}
}
+static int bma400_read_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir)
+{
+ struct bma400_data *data = iio_priv(indio_dev);
+
+ switch (chan->type) {
+ case IIO_STEPS:
+ return data->step_event_en;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int bma400_write_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir, int state)
+{
+ int ret;
+ struct bma400_data *data = iio_priv(indio_dev);
+
+ switch (chan->type) {
+ case IIO_STEPS:
+ mutex_lock(&data->mutex);
+ if (!data->steps_enabled) {
+ ret = regmap_update_bits(data->regmap,
+ BMA400_INT_CONFIG1_REG,
+ BMA400_STEP_INT_MSK,
+ FIELD_PREP(BMA400_STEP_INT_MSK,
+ 1));
+ if (ret) {
+ mutex_unlock(&data->mutex);
+ return ret;
+ }
+ data->steps_enabled = 1;
+ }
+
+ ret = regmap_update_bits(data->regmap,
+ BMA400_INT12_MAP_REG,
+ BMA400_STEP_INT_MSK,
+ FIELD_PREP(BMA400_STEP_INT_MSK,
+ state));
+ mutex_unlock(&data->mutex);
+ if (ret)
+ return ret;
+ data->step_event_en = state;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
static int bma400_data_rdy_trigger_set_state(struct iio_trigger *trig,
bool state)
{
@@ -906,6 +970,8 @@ static const struct iio_info bma400_info = {
.read_avail = bma400_read_avail,
.write_raw = bma400_write_raw,
.write_raw_get_fmt = bma400_write_raw_get_fmt,
+ .read_event_config = bma400_read_event_config,
+ .write_event_config = bma400_write_event_config,
};
static const struct iio_trigger_ops bma400_trigger_ops = {
@@ -946,6 +1012,7 @@ static irqreturn_t bma400_interrupt(int irq, void *private)
{
struct iio_dev *indio_dev = private;
struct bma400_data *data = iio_priv(indio_dev);
+ s64 timestamp = iio_get_time_ns(indio_dev);
int ret;
__le16 status;
@@ -956,6 +1023,15 @@ static irqreturn_t bma400_interrupt(int irq, void *private)
if (ret)
return IRQ_NONE;
+ if (FIELD_GET(BMA400_STEP_STAT_MASK, le16_to_cpu(status))) {
+ iio_push_event(indio_dev,
+ IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD,
+ IIO_EV_DIR_NONE,
+ IIO_EV_TYPE_CHANGE, 0, 0, 0),
+ timestamp);
+ return IRQ_HANDLED;
+ }
+
if (FIELD_GET(BMA400_INT_DRDY_MSK, le16_to_cpu(status))) {
iio_trigger_poll_chained(data->trig);
return IRQ_HANDLED;
--
2.17.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 7/9] iio: accel: bma400: Add activity recognition support
2022-04-11 20:31 [PATCH v3 0/9] iio: accel: bma400: Add buffer, step and activity/inactivity Jagath Jog J
` (5 preceding siblings ...)
2022-04-11 20:31 ` [PATCH v3 6/9] iio: accel: bma400: Add step change event Jagath Jog J
@ 2022-04-11 20:31 ` Jagath Jog J
2022-04-16 16:47 ` Jonathan Cameron
2022-04-11 20:31 ` [PATCH v3 8/9] iio: accel: bma400: Add debugfs register access support Jagath Jog J
2022-04-11 20:31 ` [PATCH v3 9/9] iio: accel: bma400: Add support for activity and inactivity events Jagath Jog J
8 siblings, 1 reply; 30+ messages in thread
From: Jagath Jog J @ 2022-04-11 20:31 UTC (permalink / raw)
To: dan, jic23, andy.shevchenko; +Cc: linux-iio, linux-kernel
Add support for activity recognition like STILL, WALKING, RUNNING
and these events are pushed to the userspace whenever the STEP
interrupt occurs.
Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
---
drivers/iio/accel/bma400_core.c | 104 ++++++++++++++++++++++++++++++++
1 file changed, 104 insertions(+)
diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
index 37f38626a9aa..69d2caa4ed18 100644
--- a/drivers/iio/accel/bma400_core.c
+++ b/drivers/iio/accel/bma400_core.c
@@ -59,6 +59,12 @@ struct bma400_sample_freq {
int uhz;
};
+enum bma400_activity {
+ BMA400_STILL,
+ BMA400_WALKING,
+ BMA400_RUNNING,
+};
+
struct bma400_data {
struct device *dev;
struct regmap *regmap;
@@ -72,6 +78,7 @@ struct bma400_data {
struct iio_trigger *trig;
int steps_enabled;
bool step_event_en;
+ bool activity_event_en;
/* Correct time stamp alignment */
struct {
__le16 buff[3];
@@ -175,6 +182,12 @@ static const struct iio_event_spec bma400_step_detect_event = {
.mask_separate = BIT(IIO_EV_INFO_ENABLE),
};
+static const struct iio_event_spec bma400_activity_event = {
+ .type = IIO_EV_TYPE_CHANGE,
+ .dir = IIO_EV_DIR_NONE,
+ .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE),
+};
+
#define BMA400_ACC_CHANNEL(_index, _axis) { \
.type = IIO_ACCEL, \
.modified = 1, \
@@ -196,6 +209,16 @@ static const struct iio_event_spec bma400_step_detect_event = {
}, \
}
+#define BMA400_ACTIVITY_CHANNEL(_chan2) { \
+ .type = IIO_ACTIVITY, \
+ .modified = 1, \
+ .channel2 = _chan2, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
+ .scan_index = -1, /* No buffer support */ \
+ .event_spec = &bma400_activity_event, \
+ .num_event_specs = 1, \
+}
+
static const struct iio_chan_spec bma400_channels[] = {
BMA400_ACC_CHANNEL(0, X),
BMA400_ACC_CHANNEL(1, Y),
@@ -220,6 +243,9 @@ static const struct iio_chan_spec bma400_channels[] = {
.event_spec = &bma400_step_detect_event,
.num_event_specs = 1,
},
+ BMA400_ACTIVITY_CHANNEL(IIO_MOD_STILL),
+ BMA400_ACTIVITY_CHANNEL(IIO_MOD_WALKING),
+ BMA400_ACTIVITY_CHANNEL(IIO_MOD_RUNNING),
IIO_CHAN_SOFT_TIMESTAMP(4),
};
@@ -626,6 +652,20 @@ static void bma400_power_disable(void *data_ptr)
ERR_PTR(ret));
}
+static enum iio_modifier bma400_act_to_mod(enum bma400_activity activity)
+{
+ switch (activity) {
+ case BMA400_STILL:
+ return IIO_MOD_STILL;
+ case BMA400_WALKING:
+ return IIO_MOD_WALKING;
+ case BMA400_RUNNING:
+ return IIO_MOD_RUNNING;
+ default:
+ return IIO_NO_MOD;
+ }
+}
+
static int bma400_init(struct bma400_data *data)
{
unsigned int val;
@@ -725,6 +765,7 @@ static int bma400_read_raw(struct iio_dev *indio_dev,
struct bma400_data *data = iio_priv(indio_dev);
int ret;
u8 steps_raw[3];
+ unsigned int activity;
switch (mask) {
case IIO_CHAN_INFO_PROCESSED:
@@ -743,6 +784,23 @@ static int bma400_read_raw(struct iio_dev *indio_dev,
return ret;
*val = get_unaligned_le24(steps_raw);
return IIO_VAL_INT;
+ case IIO_ACTIVITY:
+ mutex_lock(&data->mutex);
+ ret = regmap_read(data->regmap, BMA400_STEP_STAT_REG,
+ &activity);
+ mutex_unlock(&data->mutex);
+ if (ret)
+ return ret;
+ /*
+ * The device does not support confidence value levels,
+ * so we will always have 100% for current activity and
+ * 0% for the others.
+ */
+ if (chan->channel2 == bma400_act_to_mod(activity))
+ *val = 100;
+ else
+ *val = 0;
+ return IIO_VAL_INT;
default:
return -EINVAL;
}
@@ -898,6 +956,8 @@ static int bma400_read_event_config(struct iio_dev *indio_dev,
switch (chan->type) {
case IIO_STEPS:
return data->step_event_en;
+ case IIO_ACTIVITY:
+ return data->activity_event_en;
default:
return -EINVAL;
}
@@ -937,6 +997,32 @@ static int bma400_write_event_config(struct iio_dev *indio_dev,
return ret;
data->step_event_en = state;
return 0;
+ case IIO_ACTIVITY:
+ if (!data->step_event_en) {
+ mutex_lock(&data->mutex);
+ ret = regmap_update_bits(data->regmap,
+ BMA400_INT_CONFIG1_REG,
+ BMA400_STEP_INT_MSK,
+ FIELD_PREP(BMA400_STEP_INT_MSK,
+ 1));
+ if (ret) {
+ mutex_unlock(&data->mutex);
+ return ret;
+ }
+ data->steps_enabled = 1;
+
+ ret = regmap_update_bits(data->regmap,
+ BMA400_INT12_MAP_REG,
+ BMA400_STEP_INT_MSK,
+ FIELD_PREP(BMA400_STEP_INT_MSK,
+ 1));
+ mutex_unlock(&data->mutex);
+ if (ret)
+ return ret;
+ data->step_event_en = 1;
+ }
+ data->activity_event_en = state;
+ return 0;
default:
return -EINVAL;
}
@@ -1015,6 +1101,7 @@ static irqreturn_t bma400_interrupt(int irq, void *private)
s64 timestamp = iio_get_time_ns(indio_dev);
int ret;
__le16 status;
+ unsigned int act;
mutex_lock(&data->mutex);
ret = regmap_bulk_read(data->regmap, BMA400_INT_STAT0_REG, &status,
@@ -1029,6 +1116,23 @@ static irqreturn_t bma400_interrupt(int irq, void *private)
IIO_EV_DIR_NONE,
IIO_EV_TYPE_CHANGE, 0, 0, 0),
timestamp);
+
+ if (data->activity_event_en) {
+ mutex_lock(&data->mutex);
+ ret = regmap_read(data->regmap, BMA400_STEP_STAT_REG,
+ &act);
+ mutex_unlock(&data->mutex);
+ if (ret)
+ return IRQ_NONE;
+
+ iio_push_event(indio_dev,
+ IIO_EVENT_CODE(IIO_ACTIVITY, 0,
+ bma400_act_to_mod(act),
+ IIO_EV_DIR_NONE,
+ IIO_EV_TYPE_CHANGE, 0,
+ 0, 0),
+ timestamp);
+ }
return IRQ_HANDLED;
}
--
2.17.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 8/9] iio: accel: bma400: Add debugfs register access support
2022-04-11 20:31 [PATCH v3 0/9] iio: accel: bma400: Add buffer, step and activity/inactivity Jagath Jog J
` (6 preceding siblings ...)
2022-04-11 20:31 ` [PATCH v3 7/9] iio: accel: bma400: Add activity recognition support Jagath Jog J
@ 2022-04-11 20:31 ` Jagath Jog J
2022-04-16 16:48 ` Jonathan Cameron
2022-04-11 20:31 ` [PATCH v3 9/9] iio: accel: bma400: Add support for activity and inactivity events Jagath Jog J
8 siblings, 1 reply; 30+ messages in thread
From: Jagath Jog J @ 2022-04-11 20:31 UTC (permalink / raw)
To: dan, jic23, andy.shevchenko; +Cc: linux-iio, linux-kernel
Add support to read/write byte from/to bma400 device from the userspace
using debugfs interface.
Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
---
drivers/iio/accel/bma400_core.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
index 69d2caa4ed18..b6c79cfabaa4 100644
--- a/drivers/iio/accel/bma400_core.c
+++ b/drivers/iio/accel/bma400_core.c
@@ -1028,6 +1028,23 @@ static int bma400_write_event_config(struct iio_dev *indio_dev,
}
}
+static int bma400_debugfs_reg_access(struct iio_dev *indio_dev,
+ unsigned int reg,
+ unsigned int writeval,
+ unsigned int *readval)
+{
+ struct bma400_data *data = iio_priv(indio_dev);
+ int ret;
+
+ mutex_lock(&data->mutex);
+ if (readval)
+ ret = regmap_read(data->regmap, reg, readval);
+ else
+ ret = regmap_write(data->regmap, reg, writeval);
+ mutex_unlock(&data->mutex);
+ return ret;
+}
+
static int bma400_data_rdy_trigger_set_state(struct iio_trigger *trig,
bool state)
{
@@ -1058,6 +1075,7 @@ static const struct iio_info bma400_info = {
.write_raw_get_fmt = bma400_write_raw_get_fmt,
.read_event_config = bma400_read_event_config,
.write_event_config = bma400_write_event_config,
+ .debugfs_reg_access = bma400_debugfs_reg_access,
};
static const struct iio_trigger_ops bma400_trigger_ops = {
--
2.17.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH v3 9/9] iio: accel: bma400: Add support for activity and inactivity events
2022-04-11 20:31 [PATCH v3 0/9] iio: accel: bma400: Add buffer, step and activity/inactivity Jagath Jog J
` (7 preceding siblings ...)
2022-04-11 20:31 ` [PATCH v3 8/9] iio: accel: bma400: Add debugfs register access support Jagath Jog J
@ 2022-04-11 20:31 ` Jagath Jog J
2022-04-12 5:21 ` kernel test robot
` (2 more replies)
8 siblings, 3 replies; 30+ messages in thread
From: Jagath Jog J @ 2022-04-11 20:31 UTC (permalink / raw)
To: dan, jic23, andy.shevchenko; +Cc: linux-iio, linux-kernel
Add support for activity and inactivity events for all axis based on the
threshold, duration and hysteresis value set from the userspace. INT1 pin
is used to interrupt and event is pushed to userspace.
Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
---
drivers/iio/accel/bma400.h | 11 ++
drivers/iio/accel/bma400_core.c | 229 ++++++++++++++++++++++++++++++++
2 files changed, 240 insertions(+)
diff --git a/drivers/iio/accel/bma400.h b/drivers/iio/accel/bma400.h
index bc4641279be3..cbf8035c817e 100644
--- a/drivers/iio/accel/bma400.h
+++ b/drivers/iio/accel/bma400.h
@@ -93,6 +93,17 @@
#define BMA400_ACC_ODR_MIN_WHOLE_HZ 25
#define BMA400_ACC_ODR_MIN_HZ 12
+/* Generic interrupts register */
+#define BMA400_GEN1INT_CONFIG0 0x3f
+#define BMA400_GEN2INT_CONFIG0 0x4A
+#define BMA400_GEN_CONFIG1_OFF 0x01
+#define BMA400_GEN_CONFIG2_OFF 0x02
+#define BMA400_GEN_CONFIG3_OFF 0x03
+#define BMA400_GEN_CONFIG31_OFF 0x04
+#define BMA400_INT_GEN1_MSK BIT(2)
+#define BMA400_INT_GEN2_MSK BIT(3)
+#define BMA400_GEN_HYST_MSK GENMASK(1, 0)
+
/*
* BMA400_SCALE_MIN macro value represents m/s^2 for 1 LSB before
* converting to micro values for +-2g range.
diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
index b6c79cfabaa4..226a5f63d1a6 100644
--- a/drivers/iio/accel/bma400_core.c
+++ b/drivers/iio/accel/bma400_core.c
@@ -79,6 +79,7 @@ struct bma400_data {
int steps_enabled;
bool step_event_en;
bool activity_event_en;
+ u8 generic_event_en;
/* Correct time stamp alignment */
struct {
__le16 buff[3];
@@ -188,6 +189,25 @@ static const struct iio_event_spec bma400_activity_event = {
.mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE),
};
+static const struct iio_event_spec bma400_accel_event[] = {
+ {
+ .type = IIO_EV_TYPE_MAG,
+ .dir = IIO_EV_DIR_FALLING,
+ .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
+ BIT(IIO_EV_INFO_PERIOD) |
+ BIT(IIO_EV_INFO_HYSTERESIS) |
+ BIT(IIO_EV_INFO_ENABLE),
+ },
+ {
+ .type = IIO_EV_TYPE_MAG,
+ .dir = IIO_EV_DIR_RISING,
+ .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
+ BIT(IIO_EV_INFO_PERIOD) |
+ BIT(IIO_EV_INFO_HYSTERESIS) |
+ BIT(IIO_EV_INFO_ENABLE),
+ },
+};
+
#define BMA400_ACC_CHANNEL(_index, _axis) { \
.type = IIO_ACCEL, \
.modified = 1, \
@@ -207,6 +227,8 @@ static const struct iio_event_spec bma400_activity_event = {
.storagebits = 16, \
.endianness = IIO_LE, \
}, \
+ .event_spec = bma400_accel_event, \
+ .num_event_specs = ARRAY_SIZE(bma400_accel_event) \
}
#define BMA400_ACTIVITY_CHANNEL(_chan2) { \
@@ -954,6 +976,17 @@ static int bma400_read_event_config(struct iio_dev *indio_dev,
struct bma400_data *data = iio_priv(indio_dev);
switch (chan->type) {
+ case IIO_ACCEL:
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ return FIELD_GET(BMA400_INT_GEN1_MSK,
+ data->generic_event_en);
+ case IIO_EV_DIR_FALLING:
+ return FIELD_GET(BMA400_INT_GEN2_MSK,
+ data->generic_event_en);
+ default:
+ return -EINVAL;
+ }
case IIO_STEPS:
return data->step_event_en;
case IIO_ACTIVITY:
@@ -970,8 +1003,74 @@ static int bma400_write_event_config(struct iio_dev *indio_dev,
{
int ret;
struct bma400_data *data = iio_priv(indio_dev);
+ int reg, msk, value, field_value;
switch (chan->type) {
+ case IIO_ACCEL:
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ reg = BMA400_GEN1INT_CONFIG0;
+ msk = BMA400_INT_GEN1_MSK;
+ value = 2;
+ field_value = FIELD_PREP(BMA400_INT_GEN1_MSK, state);
+ break;
+ case IIO_EV_DIR_FALLING:
+ reg = BMA400_GEN2INT_CONFIG0;
+ msk = BMA400_INT_GEN2_MSK;
+ value = 0;
+ field_value = FIELD_PREP(BMA400_INT_GEN2_MSK, state);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ mutex_lock(&data->mutex);
+ /* Enabling all axis for interrupt evaluation */
+ ret = regmap_write(data->regmap, reg, 0xF8);
+ if (ret) {
+ mutex_unlock(&data->mutex);
+ return ret;
+ }
+
+ /* OR combination of all axis for interrupt evaluation */
+ ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG1_OFF,
+ value);
+ if (ret) {
+ mutex_unlock(&data->mutex);
+ return ret;
+ }
+
+ /* Initial value to avoid interrupts while enabling*/
+ ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
+ 0x0A);
+ if (ret) {
+ mutex_unlock(&data->mutex);
+ return ret;
+ }
+
+ /* Initial duration value to avoid interrupts while enabling*/
+ ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG31_OFF,
+ 0x0F);
+ if (ret) {
+ mutex_unlock(&data->mutex);
+ return ret;
+ }
+
+ ret = regmap_update_bits(data->regmap, BMA400_INT1_MAP_REG,
+ msk, field_value);
+ if (ret) {
+ mutex_unlock(&data->mutex);
+ return ret;
+ }
+
+ ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG0_REG,
+ msk, field_value);
+ mutex_unlock(&data->mutex);
+ if (ret)
+ return ret;
+
+ set_mask_bits(&data->generic_event_en, msk, field_value);
+ return 0;
case IIO_STEPS:
mutex_lock(&data->mutex);
if (!data->steps_enabled) {
@@ -1028,6 +1127,118 @@ static int bma400_write_event_config(struct iio_dev *indio_dev,
}
}
+static int get_gen_config_reg(enum iio_event_direction dir)
+{
+ switch (dir) {
+ case IIO_EV_DIR_FALLING:
+ return BMA400_GEN2INT_CONFIG0;
+ case IIO_EV_DIR_RISING:
+ return BMA400_GEN1INT_CONFIG0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int bma400_read_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int *val, int *val2)
+{
+ struct bma400_data *data = iio_priv(indio_dev);
+ int ret;
+ u8 reg, duration[2];
+
+ reg = get_gen_config_reg(dir);
+ if (reg < 0)
+ return -EINVAL;
+
+ *val2 = 0;
+ switch (info) {
+ case IIO_EV_INFO_VALUE:
+ mutex_lock(&data->mutex);
+ ret = regmap_read(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
+ val);
+ mutex_unlock(&data->mutex);
+ if (ret)
+ return ret;
+ return IIO_VAL_INT;
+ case IIO_EV_INFO_PERIOD:
+ mutex_lock(&data->mutex);
+ ret = regmap_bulk_read(data->regmap,
+ reg + BMA400_GEN_CONFIG3_OFF,
+ duration, sizeof(duration));
+ mutex_unlock(&data->mutex);
+ if (ret)
+ return ret;
+ *val = get_unaligned_be16(duration);
+ return IIO_VAL_INT;
+ case IIO_EV_INFO_HYSTERESIS:
+ mutex_lock(&data->mutex);
+ ret = regmap_read(data->regmap, reg, val);
+ mutex_unlock(&data->mutex);
+ if (ret)
+ return ret;
+ *val = FIELD_GET(BMA400_GEN_HYST_MSK, *val);
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int bma400_write_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int val, int val2)
+{
+ struct bma400_data *data = iio_priv(indio_dev);
+ int ret;
+ u8 reg, duration[2];
+
+ reg = get_gen_config_reg(dir);
+ if (reg < 0)
+ return -EINVAL;
+
+ switch (info) {
+ case IIO_EV_INFO_VALUE:
+ if (val < 1 || val > 255)
+ return -EINVAL;
+
+ mutex_lock(&data->mutex);
+ ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
+ val);
+ mutex_unlock(&data->mutex);
+ return ret;
+ case IIO_EV_INFO_PERIOD:
+ if (val < 1 || val > 65535)
+ return -EINVAL;
+
+ put_unaligned_be16(val, duration);
+
+ mutex_lock(&data->mutex);
+ ret = regmap_bulk_write(data->regmap,
+ reg + BMA400_GEN_CONFIG3_OFF,
+ duration, sizeof(duration));
+ mutex_unlock(&data->mutex);
+ return ret;
+ case IIO_EV_INFO_HYSTERESIS:
+ if (val < 0 || val > 3)
+ return -EINVAL;
+
+ mutex_lock(&data->mutex);
+ ret = regmap_update_bits(data->regmap, reg,
+ BMA400_GEN_HYST_MSK,
+ FIELD_PREP(BMA400_GEN_HYST_MSK, val));
+ mutex_unlock(&data->mutex);
+ return ret;
+ default:
+ return -EINVAL;
+ }
+}
+
static int bma400_debugfs_reg_access(struct iio_dev *indio_dev,
unsigned int reg,
unsigned int writeval,
@@ -1076,6 +1287,8 @@ static const struct iio_info bma400_info = {
.read_event_config = bma400_read_event_config,
.write_event_config = bma400_write_event_config,
.debugfs_reg_access = bma400_debugfs_reg_access,
+ .write_event_value = bma400_write_event_value,
+ .read_event_value = bma400_read_event_value,
};
static const struct iio_trigger_ops bma400_trigger_ops = {
@@ -1120,6 +1333,7 @@ static irqreturn_t bma400_interrupt(int irq, void *private)
int ret;
__le16 status;
unsigned int act;
+ unsigned int ev_dir = IIO_EV_DIR_NONE;
mutex_lock(&data->mutex);
ret = regmap_bulk_read(data->regmap, BMA400_INT_STAT0_REG, &status,
@@ -1128,6 +1342,21 @@ static irqreturn_t bma400_interrupt(int irq, void *private)
if (ret)
return IRQ_NONE;
+ if (FIELD_GET(BMA400_INT_GEN1_MSK, le16_to_cpu(status)))
+ ev_dir = IIO_EV_DIR_RISING;
+
+ if (FIELD_GET(BMA400_INT_GEN2_MSK, le16_to_cpu(status)))
+ ev_dir = IIO_EV_DIR_FALLING;
+
+ if (ev_dir != IIO_EV_DIR_NONE) {
+ iio_push_event(indio_dev,
+ IIO_MOD_EVENT_CODE(IIO_ACCEL, 0,
+ IIO_MOD_X_OR_Y_OR_Z,
+ IIO_EV_TYPE_MAG, ev_dir),
+ timestamp);
+ return IRQ_HANDLED;
+ }
+
if (FIELD_GET(BMA400_STEP_STAT_MASK, le16_to_cpu(status))) {
iio_push_event(indio_dev,
IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD,
--
2.17.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH v3 9/9] iio: accel: bma400: Add support for activity and inactivity events
2022-04-11 20:31 ` [PATCH v3 9/9] iio: accel: bma400: Add support for activity and inactivity events Jagath Jog J
@ 2022-04-12 5:21 ` kernel test robot
2022-04-12 10:41 ` kernel test robot
2022-04-16 16:55 ` Jonathan Cameron
2 siblings, 0 replies; 30+ messages in thread
From: kernel test robot @ 2022-04-12 5:21 UTC (permalink / raw)
To: Jagath Jog J, dan, jic23, andy.shevchenko
Cc: llvm, kbuild-all, linux-iio, linux-kernel
Hi Jagath,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on jic23-iio/togreg]
[also build test ERROR on v5.18-rc2 next-20220411]
[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]
url: https://github.com/intel-lab-lkp/linux/commits/Jagath-Jog-J/iio-accel-bma400-Add-buffer-step-and-activity-inactivity/20220412-043436
base: https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
config: riscv-randconfig-c006-20220411 (https://download.01.org/0day-ci/archive/20220412/202204121327.f3Svxeg1-lkp@intel.com/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project fe2478d44e4f7f191c43fef629ac7a23d0251e72)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install riscv cross compiling tool for clang build
# apt-get install binutils-riscv64-linux-gnu
# https://github.com/intel-lab-lkp/linux/commit/15ee6de45ed7a028569638c198e170bb98cef4ab
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Jagath-Jog-J/iio-accel-bma400-Add-buffer-step-and-activity-inactivity/20220412-043436
git checkout 15ee6de45ed7a028569638c198e170bb98cef4ab
# save the config file to linux build tree
mkdir build_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=riscv SHELL=/bin/bash drivers/iio/accel/
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All errors (new ones prefixed by >>):
>> drivers/iio/accel/bma400_core.c:1072:3: error: call to __compiletime_assert_272 declared with 'error' attribute: BUILD_BUG failed
set_mask_bits(&data->generic_event_en, msk, field_value);
^
include/linux/bitops.h:283:11: note: expanded from macro 'set_mask_bits'
} while (cmpxchg(ptr, old__, new__) != old__); \
^
include/linux/atomic/atomic-instrumented.h:1916:2: note: expanded from macro 'cmpxchg'
arch_cmpxchg(__ai_ptr, __VA_ARGS__); \
^
arch/riscv/include/asm/cmpxchg.h:344:23: note: expanded from macro 'arch_cmpxchg'
(__typeof__(*(ptr))) __cmpxchg((ptr), \
^
note: (skipping 4 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
include/linux/compiler_types.h:340:2: note: expanded from macro '_compiletime_assert'
__compiletime_assert(condition, msg, prefix, suffix)
^
include/linux/compiler_types.h:333:4: note: expanded from macro '__compiletime_assert'
prefix ## suffix(); \
^
<scratch space>:64:1: note: expanded from here
__compiletime_assert_272
^
1 error generated.
vim +/error +1072 drivers/iio/accel/bma400_core.c
998
999 static int bma400_write_event_config(struct iio_dev *indio_dev,
1000 const struct iio_chan_spec *chan,
1001 enum iio_event_type type,
1002 enum iio_event_direction dir, int state)
1003 {
1004 int ret;
1005 struct bma400_data *data = iio_priv(indio_dev);
1006 int reg, msk, value, field_value;
1007
1008 switch (chan->type) {
1009 case IIO_ACCEL:
1010 switch (dir) {
1011 case IIO_EV_DIR_RISING:
1012 reg = BMA400_GEN1INT_CONFIG0;
1013 msk = BMA400_INT_GEN1_MSK;
1014 value = 2;
1015 field_value = FIELD_PREP(BMA400_INT_GEN1_MSK, state);
1016 break;
1017 case IIO_EV_DIR_FALLING:
1018 reg = BMA400_GEN2INT_CONFIG0;
1019 msk = BMA400_INT_GEN2_MSK;
1020 value = 0;
1021 field_value = FIELD_PREP(BMA400_INT_GEN2_MSK, state);
1022 break;
1023 default:
1024 return -EINVAL;
1025 }
1026
1027 mutex_lock(&data->mutex);
1028 /* Enabling all axis for interrupt evaluation */
1029 ret = regmap_write(data->regmap, reg, 0xF8);
1030 if (ret) {
1031 mutex_unlock(&data->mutex);
1032 return ret;
1033 }
1034
1035 /* OR combination of all axis for interrupt evaluation */
1036 ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG1_OFF,
1037 value);
1038 if (ret) {
1039 mutex_unlock(&data->mutex);
1040 return ret;
1041 }
1042
1043 /* Initial value to avoid interrupts while enabling*/
1044 ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
1045 0x0A);
1046 if (ret) {
1047 mutex_unlock(&data->mutex);
1048 return ret;
1049 }
1050
1051 /* Initial duration value to avoid interrupts while enabling*/
1052 ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG31_OFF,
1053 0x0F);
1054 if (ret) {
1055 mutex_unlock(&data->mutex);
1056 return ret;
1057 }
1058
1059 ret = regmap_update_bits(data->regmap, BMA400_INT1_MAP_REG,
1060 msk, field_value);
1061 if (ret) {
1062 mutex_unlock(&data->mutex);
1063 return ret;
1064 }
1065
1066 ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG0_REG,
1067 msk, field_value);
1068 mutex_unlock(&data->mutex);
1069 if (ret)
1070 return ret;
1071
> 1072 set_mask_bits(&data->generic_event_en, msk, field_value);
1073 return 0;
1074 case IIO_STEPS:
1075 mutex_lock(&data->mutex);
1076 if (!data->steps_enabled) {
1077 ret = regmap_update_bits(data->regmap,
1078 BMA400_INT_CONFIG1_REG,
1079 BMA400_STEP_INT_MSK,
1080 FIELD_PREP(BMA400_STEP_INT_MSK,
1081 1));
1082 if (ret) {
1083 mutex_unlock(&data->mutex);
1084 return ret;
1085 }
1086 data->steps_enabled = 1;
1087 }
1088
1089 ret = regmap_update_bits(data->regmap,
1090 BMA400_INT12_MAP_REG,
1091 BMA400_STEP_INT_MSK,
1092 FIELD_PREP(BMA400_STEP_INT_MSK,
1093 state));
1094 mutex_unlock(&data->mutex);
1095 if (ret)
1096 return ret;
1097 data->step_event_en = state;
1098 return 0;
1099 case IIO_ACTIVITY:
1100 if (!data->step_event_en) {
1101 mutex_lock(&data->mutex);
1102 ret = regmap_update_bits(data->regmap,
1103 BMA400_INT_CONFIG1_REG,
1104 BMA400_STEP_INT_MSK,
1105 FIELD_PREP(BMA400_STEP_INT_MSK,
1106 1));
1107 if (ret) {
1108 mutex_unlock(&data->mutex);
1109 return ret;
1110 }
1111 data->steps_enabled = 1;
1112
1113 ret = regmap_update_bits(data->regmap,
1114 BMA400_INT12_MAP_REG,
1115 BMA400_STEP_INT_MSK,
1116 FIELD_PREP(BMA400_STEP_INT_MSK,
1117 1));
1118 mutex_unlock(&data->mutex);
1119 if (ret)
1120 return ret;
1121 data->step_event_en = 1;
1122 }
1123 data->activity_event_en = state;
1124 return 0;
1125 default:
1126 return -EINVAL;
1127 }
1128 }
1129
--
0-DAY CI Kernel Test Service
https://01.org/lkp
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 9/9] iio: accel: bma400: Add support for activity and inactivity events
2022-04-11 20:31 ` [PATCH v3 9/9] iio: accel: bma400: Add support for activity and inactivity events Jagath Jog J
2022-04-12 5:21 ` kernel test robot
@ 2022-04-12 7:38 ` Dan Carpenter
2022-04-16 16:55 ` Jonathan Cameron
2 siblings, 0 replies; 30+ messages in thread
From: kernel test robot @ 2022-04-12 6:44 UTC (permalink / raw)
To: kbuild
[-- Attachment #1: Type: text/plain, Size: 8982 bytes --]
CC: kbuild-all(a)lists.01.org
BCC: lkp(a)intel.com
In-Reply-To: <20220411203133.19929-10-jagathjog1996@gmail.com>
References: <20220411203133.19929-10-jagathjog1996@gmail.com>
TO: Jagath Jog J <jagathjog1996@gmail.com>
TO: dan(a)dlrobertson.com
TO: jic23(a)kernel.org
TO: andy.shevchenko(a)gmail.com
CC: linux-iio(a)vger.kernel.org
CC: linux-kernel(a)vger.kernel.org
Hi Jagath,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on jic23-iio/togreg]
[also build test WARNING on v5.18-rc2 next-20220411]
[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]
url: https://github.com/intel-lab-lkp/linux/commits/Jagath-Jog-J/iio-accel-bma400-Add-buffer-step-and-activity-inactivity/20220412-043436
base: https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
:::::: branch date: 10 hours ago
:::::: commit date: 10 hours ago
config: x86_64-randconfig-m001-20220411 (https://download.01.org/0day-ci/archive/20220412/202204121411.snZVqiMy-lkp(a)intel.com/config)
compiler: gcc-11 (Debian 11.2.0-19) 11.2.0
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
smatch warnings:
drivers/iio/accel/bma400_core.c:1154 bma400_read_event_value() warn: impossible condition '(reg < 0) => (0-255 < 0)'
drivers/iio/accel/bma400_core.c:1202 bma400_write_event_value() warn: impossible condition '(reg < 0) => (0-255 < 0)'
vim +1154 drivers/iio/accel/bma400_core.c
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1141
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1142 static int bma400_read_event_value(struct iio_dev *indio_dev,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1143 const struct iio_chan_spec *chan,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1144 enum iio_event_type type,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1145 enum iio_event_direction dir,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1146 enum iio_event_info info,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1147 int *val, int *val2)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1148 {
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1149 struct bma400_data *data = iio_priv(indio_dev);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1150 int ret;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1151 u8 reg, duration[2];
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1152
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1153 reg = get_gen_config_reg(dir);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 @1154 if (reg < 0)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1155 return -EINVAL;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1156
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1157 *val2 = 0;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1158 switch (info) {
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1159 case IIO_EV_INFO_VALUE:
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1160 mutex_lock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1161 ret = regmap_read(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1162 val);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1163 mutex_unlock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1164 if (ret)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1165 return ret;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1166 return IIO_VAL_INT;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1167 case IIO_EV_INFO_PERIOD:
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1168 mutex_lock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1169 ret = regmap_bulk_read(data->regmap,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1170 reg + BMA400_GEN_CONFIG3_OFF,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1171 duration, sizeof(duration));
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1172 mutex_unlock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1173 if (ret)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1174 return ret;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1175 *val = get_unaligned_be16(duration);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1176 return IIO_VAL_INT;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1177 case IIO_EV_INFO_HYSTERESIS:
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1178 mutex_lock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1179 ret = regmap_read(data->regmap, reg, val);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1180 mutex_unlock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1181 if (ret)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1182 return ret;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1183 *val = FIELD_GET(BMA400_GEN_HYST_MSK, *val);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1184 return IIO_VAL_INT;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1185 default:
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1186 return -EINVAL;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1187 }
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1188 }
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1189
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1190 static int bma400_write_event_value(struct iio_dev *indio_dev,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1191 const struct iio_chan_spec *chan,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1192 enum iio_event_type type,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1193 enum iio_event_direction dir,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1194 enum iio_event_info info,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1195 int val, int val2)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1196 {
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1197 struct bma400_data *data = iio_priv(indio_dev);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1198 int ret;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1199 u8 reg, duration[2];
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1200
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1201 reg = get_gen_config_reg(dir);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 @1202 if (reg < 0)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1203 return -EINVAL;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1204
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1205 switch (info) {
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1206 case IIO_EV_INFO_VALUE:
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1207 if (val < 1 || val > 255)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1208 return -EINVAL;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1209
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1210 mutex_lock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1211 ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1212 val);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1213 mutex_unlock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1214 return ret;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1215 case IIO_EV_INFO_PERIOD:
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1216 if (val < 1 || val > 65535)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1217 return -EINVAL;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1218
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1219 put_unaligned_be16(val, duration);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1220
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1221 mutex_lock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1222 ret = regmap_bulk_write(data->regmap,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1223 reg + BMA400_GEN_CONFIG3_OFF,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1224 duration, sizeof(duration));
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1225 mutex_unlock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1226 return ret;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1227 case IIO_EV_INFO_HYSTERESIS:
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1228 if (val < 0 || val > 3)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1229 return -EINVAL;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1230
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1231 mutex_lock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1232 ret = regmap_update_bits(data->regmap, reg,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1233 BMA400_GEN_HYST_MSK,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1234 FIELD_PREP(BMA400_GEN_HYST_MSK, val));
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1235 mutex_unlock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1236 return ret;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1237 default:
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1238 return -EINVAL;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1239 }
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1240 }
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1241
--
0-DAY CI Kernel Test Service
https://01.org/lkp
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 9/9] iio: accel: bma400: Add support for activity and inactivity events
@ 2022-04-12 7:38 ` Dan Carpenter
0 siblings, 0 replies; 30+ messages in thread
From: Dan Carpenter @ 2022-04-12 7:38 UTC (permalink / raw)
To: kbuild, Jagath Jog J, dan, jic23, andy.shevchenko
Cc: lkp, kbuild-all, linux-iio, linux-kernel
Hi Jagath,
url: https://github.com/intel-lab-lkp/linux/commits/Jagath-Jog-J/iio-accel-bma400-Add-buffer-step-and-activity-inactivity/20220412-043436
base: https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
config: x86_64-randconfig-m001-20220411 (https://download.01.org/0day-ci/archive/20220412/202204121411.snZVqiMy-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.2.0-19) 11.2.0
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
smatch warnings:
drivers/iio/accel/bma400_core.c:1154 bma400_read_event_value() warn: impossible condition '(reg < 0) => (0-255 < 0)'
drivers/iio/accel/bma400_core.c:1202 bma400_write_event_value() warn: impossible condition '(reg < 0) => (0-255 < 0)'
vim +1154 drivers/iio/accel/bma400_core.c
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1142 static int bma400_read_event_value(struct iio_dev *indio_dev,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1143 const struct iio_chan_spec *chan,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1144 enum iio_event_type type,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1145 enum iio_event_direction dir,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1146 enum iio_event_info info,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1147 int *val, int *val2)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1148 {
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1149 struct bma400_data *data = iio_priv(indio_dev);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1150 int ret;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1151 u8 reg, duration[2];
^^^^^^
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1152
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1153 reg = get_gen_config_reg(dir);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 @1154 if (reg < 0)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1155 return -EINVAL;
Condition is impossible. Also propagate the return? if (ret < 0) return ret;?
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1156
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1157 *val2 = 0;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1158 switch (info) {
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1159 case IIO_EV_INFO_VALUE:
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1160 mutex_lock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1161 ret = regmap_read(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1162 val);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1163 mutex_unlock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1164 if (ret)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1165 return ret;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1166 return IIO_VAL_INT;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1167 case IIO_EV_INFO_PERIOD:
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1168 mutex_lock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1169 ret = regmap_bulk_read(data->regmap,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1170 reg + BMA400_GEN_CONFIG3_OFF,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1171 duration, sizeof(duration));
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1172 mutex_unlock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1173 if (ret)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1174 return ret;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1175 *val = get_unaligned_be16(duration);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1176 return IIO_VAL_INT;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1177 case IIO_EV_INFO_HYSTERESIS:
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1178 mutex_lock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1179 ret = regmap_read(data->regmap, reg, val);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1180 mutex_unlock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1181 if (ret)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1182 return ret;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1183 *val = FIELD_GET(BMA400_GEN_HYST_MSK, *val);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1184 return IIO_VAL_INT;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1185 default:
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1186 return -EINVAL;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1187 }
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1188 }
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1189
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1190 static int bma400_write_event_value(struct iio_dev *indio_dev,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1191 const struct iio_chan_spec *chan,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1192 enum iio_event_type type,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1193 enum iio_event_direction dir,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1194 enum iio_event_info info,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1195 int val, int val2)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1196 {
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1197 struct bma400_data *data = iio_priv(indio_dev);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1198 int ret;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1199 u8 reg, duration[2];
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1200
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1201 reg = get_gen_config_reg(dir);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 @1202 if (reg < 0)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1203 return -EINVAL;
Same.
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1204
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1205 switch (info) {
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1206 case IIO_EV_INFO_VALUE:
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1207 if (val < 1 || val > 255)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1208 return -EINVAL;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1209
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1210 mutex_lock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1211 ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
--
0-DAY CI Kernel Test Service
https://01.org/lkp
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 9/9] iio: accel: bma400: Add support for activity and inactivity events
@ 2022-04-12 7:38 ` Dan Carpenter
0 siblings, 0 replies; 30+ messages in thread
From: Dan Carpenter @ 2022-04-12 7:38 UTC (permalink / raw)
To: kbuild-all
[-- Attachment #1: Type: text/plain, Size: 6202 bytes --]
Hi Jagath,
url: https://github.com/intel-lab-lkp/linux/commits/Jagath-Jog-J/iio-accel-bma400-Add-buffer-step-and-activity-inactivity/20220412-043436
base: https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
config: x86_64-randconfig-m001-20220411 (https://download.01.org/0day-ci/archive/20220412/202204121411.snZVqiMy-lkp(a)intel.com/config)
compiler: gcc-11 (Debian 11.2.0-19) 11.2.0
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
smatch warnings:
drivers/iio/accel/bma400_core.c:1154 bma400_read_event_value() warn: impossible condition '(reg < 0) => (0-255 < 0)'
drivers/iio/accel/bma400_core.c:1202 bma400_write_event_value() warn: impossible condition '(reg < 0) => (0-255 < 0)'
vim +1154 drivers/iio/accel/bma400_core.c
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1142 static int bma400_read_event_value(struct iio_dev *indio_dev,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1143 const struct iio_chan_spec *chan,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1144 enum iio_event_type type,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1145 enum iio_event_direction dir,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1146 enum iio_event_info info,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1147 int *val, int *val2)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1148 {
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1149 struct bma400_data *data = iio_priv(indio_dev);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1150 int ret;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1151 u8 reg, duration[2];
^^^^^^
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1152
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1153 reg = get_gen_config_reg(dir);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 @1154 if (reg < 0)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1155 return -EINVAL;
Condition is impossible. Also propagate the return? if (ret < 0) return ret;?
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1156
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1157 *val2 = 0;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1158 switch (info) {
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1159 case IIO_EV_INFO_VALUE:
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1160 mutex_lock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1161 ret = regmap_read(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1162 val);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1163 mutex_unlock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1164 if (ret)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1165 return ret;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1166 return IIO_VAL_INT;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1167 case IIO_EV_INFO_PERIOD:
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1168 mutex_lock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1169 ret = regmap_bulk_read(data->regmap,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1170 reg + BMA400_GEN_CONFIG3_OFF,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1171 duration, sizeof(duration));
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1172 mutex_unlock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1173 if (ret)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1174 return ret;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1175 *val = get_unaligned_be16(duration);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1176 return IIO_VAL_INT;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1177 case IIO_EV_INFO_HYSTERESIS:
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1178 mutex_lock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1179 ret = regmap_read(data->regmap, reg, val);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1180 mutex_unlock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1181 if (ret)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1182 return ret;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1183 *val = FIELD_GET(BMA400_GEN_HYST_MSK, *val);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1184 return IIO_VAL_INT;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1185 default:
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1186 return -EINVAL;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1187 }
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1188 }
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1189
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1190 static int bma400_write_event_value(struct iio_dev *indio_dev,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1191 const struct iio_chan_spec *chan,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1192 enum iio_event_type type,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1193 enum iio_event_direction dir,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1194 enum iio_event_info info,
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1195 int val, int val2)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1196 {
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1197 struct bma400_data *data = iio_priv(indio_dev);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1198 int ret;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1199 u8 reg, duration[2];
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1200
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1201 reg = get_gen_config_reg(dir);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 @1202 if (reg < 0)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1203 return -EINVAL;
Same.
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1204
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1205 switch (info) {
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1206 case IIO_EV_INFO_VALUE:
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1207 if (val < 1 || val > 255)
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1208 return -EINVAL;
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1209
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1210 mutex_lock(&data->mutex);
15ee6de45ed7a02 Jagath Jog J 2022-04-12 1211 ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
--
0-DAY CI Kernel Test Service
https://01.org/lkp
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 1/9] iio: accel: bma400: Fix the scale min and max macro values
2022-04-11 20:31 ` [PATCH v3 1/9] iio: accel: bma400: Fix the scale min and max macro values Jagath Jog J
@ 2022-04-12 8:59 ` Andy Shevchenko
0 siblings, 0 replies; 30+ messages in thread
From: Andy Shevchenko @ 2022-04-12 8:59 UTC (permalink / raw)
To: Jagath Jog J
Cc: Dan Robertson, Jonathan Cameron, linux-iio, Linux Kernel Mailing List
On Mon, Apr 11, 2022 at 11:31 PM Jagath Jog J <jagathjog1996@gmail.com> wrote:
>
> Changing the scale macro values to match the bma400 sensitivity
> for 1 LSB of all the available ranges.
Shouldn't this carry a Fixes tag?
> Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
> ---
> drivers/iio/accel/bma400.h | 23 +++++++++++++++++++++--
> 1 file changed, 21 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/iio/accel/bma400.h b/drivers/iio/accel/bma400.h
> index c4c8d74155c2..5d6a1976503f 100644
> --- a/drivers/iio/accel/bma400.h
> +++ b/drivers/iio/accel/bma400.h
> @@ -83,8 +83,27 @@
> #define BMA400_ACC_ODR_MIN_WHOLE_HZ 25
> #define BMA400_ACC_ODR_MIN_HZ 12
>
> -#define BMA400_SCALE_MIN 38357
> -#define BMA400_SCALE_MAX 306864
> +/*
> + * BMA400_SCALE_MIN macro value represents m/s^2 for 1 LSB before
> + * converting to micro values for +-2g range.
> + *
> + * For +-2g - 1 LSB = 0.976562 milli g = 0.009576 m/s^2
> + * For +-4g - 1 LSB = 1.953125 milli g = 0.019153 m/s^2
> + * For +-16g - 1 LSB = 7.8125 milli g = 0.076614 m/s^2
> + *
> + * The raw value which is used to select the different ranges is determined
> + * by the first bit set position from the scale value, so BMA400_SCALE_MIN
> + * should be odd.
> + *
> + * Scale values for +-2g, +-4g, +-8g and +-16g is populated into bma400_scales
are populated
> + * array by left shifting BMA400_SCALE_MIN.
> + * eg:
e.g.:
> + * To select +-2g = 9577 << 0 = raw value to write is 0.
> + * To select +-8g = 9577 << 2 = raw value to write is 2.
> + * To select +-16g = 9577 << 3 = raw value to write is 3.
> + */
> +#define BMA400_SCALE_MIN 9577
> +#define BMA400_SCALE_MAX 76617
>
> #define BMA400_NUM_REGULATORS 2
> #define BMA400_VDD_REGULATOR 0
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 2/9] iio: accel: bma400: Reordering of header files
2022-04-11 20:31 ` [PATCH v3 2/9] iio: accel: bma400: Reordering of header files Jagath Jog J
@ 2022-04-12 9:00 ` Andy Shevchenko
0 siblings, 0 replies; 30+ messages in thread
From: Andy Shevchenko @ 2022-04-12 9:00 UTC (permalink / raw)
To: Jagath Jog J
Cc: Dan Robertson, Jonathan Cameron, linux-iio, Linux Kernel Mailing List
On Mon, Apr 11, 2022 at 11:31 PM Jagath Jog J <jagathjog1996@gmail.com> wrote:
>
> Reordering of header files and removing the iio/sysfs.h since
> custom attributes are not being used in the driver.
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
> Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
> ---
> drivers/iio/accel/bma400_core.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
> index 043002fe6f63..25ad1f7339bc 100644
> --- a/drivers/iio/accel/bma400_core.c
> +++ b/drivers/iio/accel/bma400_core.c
> @@ -13,14 +13,14 @@
>
> #include <linux/bitops.h>
> #include <linux/device.h>
> -#include <linux/iio/iio.h>
> -#include <linux/iio/sysfs.h>
> #include <linux/kernel.h>
> #include <linux/module.h>
> #include <linux/mutex.h>
> #include <linux/regmap.h>
> #include <linux/regulator/consumer.h>
>
> +#include <linux/iio/iio.h>
> +
> #include "bma400.h"
>
> /*
> --
> 2.17.1
>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 3/9] iio: accel: bma400: conversion to device-managed function
2022-04-11 20:31 ` [PATCH v3 3/9] iio: accel: bma400: conversion to device-managed function Jagath Jog J
@ 2022-04-12 9:04 ` Andy Shevchenko
0 siblings, 0 replies; 30+ messages in thread
From: Andy Shevchenko @ 2022-04-12 9:04 UTC (permalink / raw)
To: Jagath Jog J
Cc: Dan Robertson, Jonathan Cameron, linux-iio, Linux Kernel Mailing List
On Mon, Apr 11, 2022 at 11:31 PM Jagath Jog J <jagathjog1996@gmail.com> wrote:
>
> This is a conversion to device-managed by using devm_iio_device_register
devm_iio_device_register()
> inside probe function. Previously the bma400 was not put into power down
> mode in some error paths in probe where it now is, but that should cause
> no harm.
>
> The dev_set_drvdata() call, bma400_remove() function and hooks in the I2C
> and SPI driver struct is removed as devm_iio_device_register function is
devm_iio_device_register()
> used to automatically unregister on driver detach.
LGTM,
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
> Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
> ---
> drivers/iio/accel/bma400.h | 2 -
> drivers/iio/accel/bma400_core.c | 77 ++++++++++++++++-----------------
> drivers/iio/accel/bma400_i2c.c | 8 ----
> drivers/iio/accel/bma400_spi.c | 6 ---
> 4 files changed, 38 insertions(+), 55 deletions(-)
>
> diff --git a/drivers/iio/accel/bma400.h b/drivers/iio/accel/bma400.h
> index 5d6a1976503f..8dbf85eeb005 100644
> --- a/drivers/iio/accel/bma400.h
> +++ b/drivers/iio/accel/bma400.h
> @@ -113,6 +113,4 @@ extern const struct regmap_config bma400_regmap_config;
>
> int bma400_probe(struct device *dev, struct regmap *regmap, const char *name);
>
> -void bma400_remove(struct device *dev);
> -
> #endif
> diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
> index 25ad1f7339bc..07674d89d978 100644
> --- a/drivers/iio/accel/bma400_core.c
> +++ b/drivers/iio/accel/bma400_core.c
> @@ -560,6 +560,26 @@ static void bma400_init_tables(void)
> }
> }
>
> +static void bma400_regulators_disable(void *data_ptr)
> +{
> + struct bma400_data *data = data_ptr;
> +
> + regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators);
> +}
> +
> +static void bma400_power_disable(void *data_ptr)
> +{
> + struct bma400_data *data = data_ptr;
> + int ret;
> +
> + mutex_lock(&data->mutex);
> + ret = bma400_set_power_mode(data, POWER_MODE_SLEEP);
> + mutex_unlock(&data->mutex);
> + if (ret)
> + dev_warn(data->dev, "Failed to put device into sleep mode (%pe)\n",
> + ERR_PTR(ret));
> +}
> +
> static int bma400_init(struct bma400_data *data)
> {
> unsigned int val;
> @@ -569,13 +589,12 @@ static int bma400_init(struct bma400_data *data)
> ret = regmap_read(data->regmap, BMA400_CHIP_ID_REG, &val);
> if (ret) {
> dev_err(data->dev, "Failed to read chip id register\n");
> - goto out;
> + return ret;
> }
>
> if (val != BMA400_ID_REG_VAL) {
> dev_err(data->dev, "Chip ID mismatch\n");
> - ret = -ENODEV;
> - goto out;
> + return -ENODEV;
> }
>
> data->regulators[BMA400_VDD_REGULATOR].supply = "vdd";
> @@ -589,27 +608,31 @@ static int bma400_init(struct bma400_data *data)
> "Failed to get regulators: %d\n",
> ret);
>
> - goto out;
> + return ret;
> }
> ret = regulator_bulk_enable(ARRAY_SIZE(data->regulators),
> data->regulators);
> if (ret) {
> dev_err(data->dev, "Failed to enable regulators: %d\n",
> ret);
> - goto out;
> + return ret;
> }
>
> + ret = devm_add_action_or_reset(data->dev, bma400_regulators_disable, data);
> + if (ret)
> + return ret;
> +
> ret = bma400_get_power_mode(data);
> if (ret) {
> dev_err(data->dev, "Failed to get the initial power-mode\n");
> - goto err_reg_disable;
> + return ret;
> }
>
> if (data->power_mode != POWER_MODE_NORMAL) {
> ret = bma400_set_power_mode(data, POWER_MODE_NORMAL);
> if (ret) {
> dev_err(data->dev, "Failed to wake up the device\n");
> - goto err_reg_disable;
> + return ret;
> }
> /*
> * TODO: The datasheet waits 1500us here in the example, but
> @@ -618,19 +641,23 @@ static int bma400_init(struct bma400_data *data)
> usleep_range(1500, 2000);
> }
>
> + ret = devm_add_action_or_reset(data->dev, bma400_power_disable, data);
> + if (ret)
> + return ret;
> +
> bma400_init_tables();
>
> ret = bma400_get_accel_output_data_rate(data);
> if (ret)
> - goto err_reg_disable;
> + return ret;
>
> ret = bma400_get_accel_oversampling_ratio(data);
> if (ret)
> - goto err_reg_disable;
> + return ret;
>
> ret = bma400_get_accel_scale(data);
> if (ret)
> - goto err_reg_disable;
> + return ret;
>
> /*
> * Once the interrupt engine is supported we might use the
> @@ -639,12 +666,6 @@ static int bma400_init(struct bma400_data *data)
> * channel.
> */
> return regmap_write(data->regmap, BMA400_ACC_CONFIG2_REG, 0x00);
> -
> -err_reg_disable:
> - regulator_bulk_disable(ARRAY_SIZE(data->regulators),
> - data->regulators);
> -out:
> - return ret;
> }
>
> static int bma400_read_raw(struct iio_dev *indio_dev,
> @@ -822,32 +843,10 @@ int bma400_probe(struct device *dev, struct regmap *regmap, const char *name)
> indio_dev->num_channels = ARRAY_SIZE(bma400_channels);
> indio_dev->modes = INDIO_DIRECT_MODE;
>
> - dev_set_drvdata(dev, indio_dev);
> -
> - return iio_device_register(indio_dev);
> + return devm_iio_device_register(dev, indio_dev);
> }
> EXPORT_SYMBOL_NS(bma400_probe, IIO_BMA400);
>
> -void bma400_remove(struct device *dev)
> -{
> - struct iio_dev *indio_dev = dev_get_drvdata(dev);
> - struct bma400_data *data = iio_priv(indio_dev);
> - int ret;
> -
> - mutex_lock(&data->mutex);
> - ret = bma400_set_power_mode(data, POWER_MODE_SLEEP);
> - mutex_unlock(&data->mutex);
> -
> - if (ret)
> - dev_warn(dev, "Failed to put device into sleep mode (%pe)\n", ERR_PTR(ret));
> -
> - regulator_bulk_disable(ARRAY_SIZE(data->regulators),
> - data->regulators);
> -
> - iio_device_unregister(indio_dev);
> -}
> -EXPORT_SYMBOL_NS(bma400_remove, IIO_BMA400);
> -
> MODULE_AUTHOR("Dan Robertson <dan@dlrobertson.com>");
> MODULE_DESCRIPTION("Bosch BMA400 triaxial acceleration sensor core");
> MODULE_LICENSE("GPL");
> diff --git a/drivers/iio/accel/bma400_i2c.c b/drivers/iio/accel/bma400_i2c.c
> index da104ffd3fe0..4f6e01a3b3a1 100644
> --- a/drivers/iio/accel/bma400_i2c.c
> +++ b/drivers/iio/accel/bma400_i2c.c
> @@ -27,13 +27,6 @@ static int bma400_i2c_probe(struct i2c_client *client,
> return bma400_probe(&client->dev, regmap, id->name);
> }
>
> -static int bma400_i2c_remove(struct i2c_client *client)
> -{
> - bma400_remove(&client->dev);
> -
> - return 0;
> -}
> -
> static const struct i2c_device_id bma400_i2c_ids[] = {
> { "bma400", 0 },
> { }
> @@ -52,7 +45,6 @@ static struct i2c_driver bma400_i2c_driver = {
> .of_match_table = bma400_of_i2c_match,
> },
> .probe = bma400_i2c_probe,
> - .remove = bma400_i2c_remove,
> .id_table = bma400_i2c_ids,
> };
>
> diff --git a/drivers/iio/accel/bma400_spi.c b/drivers/iio/accel/bma400_spi.c
> index 51f23bdc0ea5..28e240400a3f 100644
> --- a/drivers/iio/accel/bma400_spi.c
> +++ b/drivers/iio/accel/bma400_spi.c
> @@ -87,11 +87,6 @@ static int bma400_spi_probe(struct spi_device *spi)
> return bma400_probe(&spi->dev, regmap, id->name);
> }
>
> -static void bma400_spi_remove(struct spi_device *spi)
> -{
> - bma400_remove(&spi->dev);
> -}
> -
> static const struct spi_device_id bma400_spi_ids[] = {
> { "bma400", 0 },
> { }
> @@ -110,7 +105,6 @@ static struct spi_driver bma400_spi_driver = {
> .of_match_table = bma400_of_spi_match,
> },
> .probe = bma400_spi_probe,
> - .remove = bma400_spi_remove,
> .id_table = bma400_spi_ids,
> };
>
> --
> 2.17.1
>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 4/9] iio: accel: bma400: Add triggered buffer support
2022-04-11 20:31 ` [PATCH v3 4/9] iio: accel: bma400: Add triggered buffer support Jagath Jog J
@ 2022-04-12 9:12 ` Andy Shevchenko
2022-04-12 19:30 ` Jagath Jog J
2022-04-16 16:38 ` Jonathan Cameron
1 sibling, 1 reply; 30+ messages in thread
From: Andy Shevchenko @ 2022-04-12 9:12 UTC (permalink / raw)
To: Jagath Jog J
Cc: Dan Robertson, Jonathan Cameron, linux-iio, Linux Kernel Mailing List
On Mon, Apr 11, 2022 at 11:31 PM Jagath Jog J <jagathjog1996@gmail.com> wrote:
>
> Added trigger buffer support to read continuous acceleration
> data from device with data ready interrupt which is mapped
> to INT1 pin.
Can you explain the locking schema in this driver?
> + /* Configure INT1 pin to open drain */
> + ret = regmap_write(data->regmap, BMA400_INT_IO_CTRL_REG, 0x06);
> + if (ret)
> + return ret;
No locking (or regmap only locking).
...
> +static int bma400_data_rdy_trigger_set_state(struct iio_trigger *trig,
> + bool state)
> +{
> + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
> + struct bma400_data *data = iio_priv(indio_dev);
> + int ret;
> +
> + ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG0_REG,
> + BMA400_INT_DRDY_MSK,
> + FIELD_PREP(BMA400_INT_DRDY_MSK, state));
> + if (ret)
> + return ret;
> +
> + return regmap_update_bits(data->regmap, BMA400_INT1_MAP_REG,
> + BMA400_INT_DRDY_MSK,
> + FIELD_PREP(BMA400_INT_DRDY_MSK, state));
> +}
Ditto.
...
> + mutex_lock(&data->mutex);
> +
> + /* bulk read six registers, with the base being the LSB register */
> + ret = regmap_bulk_read(data->regmap, BMA400_X_AXIS_LSB_REG,
> + &data->buffer.buff, sizeof(data->buffer.buff));
> + mutex_unlock(&data->mutex);
> + if (ret)
> + return IRQ_NONE;
But here only above with locking...
> + ret = regmap_read(data->regmap, BMA400_TEMP_DATA_REG, &temp);
> + if (ret)
> + return IRQ_NONE;
...followed by no locking.
...
> + mutex_lock(&data->mutex);
> + ret = regmap_bulk_read(data->regmap, BMA400_INT_STAT0_REG, &status,
> + sizeof(status));
> + mutex_unlock(&data->mutex);
> + if (ret)
> + return IRQ_NONE;
And again with locking.
...
So,
1) Does regmap is configured with locking? What for?
2) What's the role of data->mutex?
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 9/9] iio: accel: bma400: Add support for activity and inactivity events
2022-04-11 20:31 ` [PATCH v3 9/9] iio: accel: bma400: Add support for activity and inactivity events Jagath Jog J
2022-04-12 5:21 ` kernel test robot
@ 2022-04-12 10:41 ` kernel test robot
2022-04-16 16:55 ` Jonathan Cameron
2 siblings, 0 replies; 30+ messages in thread
From: kernel test robot @ 2022-04-12 10:41 UTC (permalink / raw)
To: Jagath Jog J, dan, jic23, andy.shevchenko
Cc: kbuild-all, linux-iio, linux-kernel
Hi Jagath,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on jic23-iio/togreg]
[also build test ERROR on v5.18-rc2 next-20220412]
[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]
url: https://github.com/intel-lab-lkp/linux/commits/Jagath-Jog-J/iio-accel-bma400-Add-buffer-step-and-activity-inactivity/20220412-043436
base: https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
config: mips-allmodconfig (https://download.01.org/0day-ci/archive/20220412/202204121837.e1RdwIqu-lkp@intel.com/config)
compiler: mips-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/15ee6de45ed7a028569638c198e170bb98cef4ab
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Jagath-Jog-J/iio-accel-bma400-Add-buffer-step-and-activity-inactivity/20220412-043436
git checkout 15ee6de45ed7a028569638c198e170bb98cef4ab
# save the config file to linux build tree
mkdir build_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=mips SHELL=/bin/bash
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All errors (new ones prefixed by >>, old ones prefixed by <<):
>> ERROR: modpost: "__cmpxchg_small" [drivers/iio/accel/bma400_core.ko] undefined!
--
0-DAY CI Kernel Test Service
https://01.org/lkp
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 4/9] iio: accel: bma400: Add triggered buffer support
2022-04-12 9:12 ` Andy Shevchenko
@ 2022-04-12 19:30 ` Jagath Jog J
[not found] ` <CAHp75Vc9MO2GxX81JQfzGRjM=nWLaQ-Uy9bV-dR1GMj1oQwjSQ@mail.gmail.com>
0 siblings, 1 reply; 30+ messages in thread
From: Jagath Jog J @ 2022-04-12 19:30 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Dan Robertson, Jonathan Cameron, linux-iio, Linux Kernel Mailing List
Hello Andy,
On Tue, Apr 12, 2022 at 12:12:21PM +0300, Andy Shevchenko wrote:
> On Mon, Apr 11, 2022 at 11:31 PM Jagath Jog J <jagathjog1996@gmail.com> wrote:
> >
> > Added trigger buffer support to read continuous acceleration
> > data from device with data ready interrupt which is mapped
> > to INT1 pin.
>
> Can you explain the locking schema in this driver?
>
> > + /* Configure INT1 pin to open drain */
> > + ret = regmap_write(data->regmap, BMA400_INT_IO_CTRL_REG, 0x06);
> > + if (ret)
> > + return ret;
>
> No locking (or regmap only locking).
This is bma400_init() function which will run when probe runs so there is no
locking in this bma400_init().
>
> ...
>
> > +static int bma400_data_rdy_trigger_set_state(struct iio_trigger *trig,
> > + bool state)
> > +{
> > + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
> > + struct bma400_data *data = iio_priv(indio_dev);
> > + int ret;
> > +
> > + ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG0_REG,
> > + BMA400_INT_DRDY_MSK,
> > + FIELD_PREP(BMA400_INT_DRDY_MSK, state));
> > + if (ret)
> > + return ret;
> > +
> > + return regmap_update_bits(data->regmap, BMA400_INT1_MAP_REG,
> > + BMA400_INT_DRDY_MSK,
> > + FIELD_PREP(BMA400_INT_DRDY_MSK, state));
> > +}
>
> Ditto.
Sorry, I missed this.
I will add lock and unlocking in the next patch.
>
> ...
>
> > + mutex_lock(&data->mutex);
> > +
> > + /* bulk read six registers, with the base being the LSB register */
> > + ret = regmap_bulk_read(data->regmap, BMA400_X_AXIS_LSB_REG,
> > + &data->buffer.buff, sizeof(data->buffer.buff));
> > + mutex_unlock(&data->mutex);
> > + if (ret)
> > + return IRQ_NONE;
>
> But here only above with locking...
>
> > + ret = regmap_read(data->regmap, BMA400_TEMP_DATA_REG, &temp);
> > + if (ret)
> > + return IRQ_NONE;
>
> ...followed by no locking.
Okay I will add lock in the next patch.
>
> ...
>
> > + mutex_lock(&data->mutex);
> > + ret = regmap_bulk_read(data->regmap, BMA400_INT_STAT0_REG, &status,
> > + sizeof(status));
> > + mutex_unlock(&data->mutex);
> > + if (ret)
> > + return IRQ_NONE;
>
> And again with locking.
>
> ...
>
> So,
> 1) Does regmap is configured with locking? What for?
> 2) What's the role of data->mutex?
1.
NO, regmap is not configured with locking.
In the regmap_config structure variable below these members are not defined
in the driver.
struct regmap_config {
regmap_lock lock;
regmap_unlock unlock;
void *lock_arg;
2.
data->mutex is used to protect the register read, write access from the device.
Is the regmap functions handle locking and unlocking internally if these below
struct members are not defined?
regmap_lock lock;
regmap_unlock unlock;
void *lock_arg;
>
> --
> With Best Regards,
> Andy Shevchenko
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 4/9] iio: accel: bma400: Add triggered buffer support
[not found] ` <CAHp75Vef21YmiKAvz-Kt-C=jb+mMCJeV_fwPAza9UwCuKy6omQ@mail.gmail.com>
@ 2022-04-13 14:23 ` Jagath Jog J
2022-04-14 13:22 ` Jagath Jog J
0 siblings, 1 reply; 30+ messages in thread
From: Jagath Jog J @ 2022-04-13 14:23 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Dan Robertson, Jonathan Cameron, linux-iio, Linux Kernel Mailing List
On Wed, Apr 13, 2022 at 12:24:54AM +0300, Andy Shevchenko wrote:
> On Wednesday, April 13, 2022, Andy Shevchenko <andy.shevchenko@gmail.com>
> wrote:
>
> >
> >
> > On Tuesday, April 12, 2022, Jagath Jog J <jagathjog1996@gmail.com> wrote:
> >
> >> Hello Andy,
> >>
> >> On Tue, Apr 12, 2022 at 12:12:21PM +0300, Andy Shevchenko wrote:
> >> > On Mon, Apr 11, 2022 at 11:31 PM Jagath Jog J <jagathjog1996@gmail.com>
> >> wrote:
> >> > >
> >> > > Added trigger buffer support to read continuous acceleration
> >> > > data from device with data ready interrupt which is mapped
> >> > > to INT1 pin.
> >> >
> >> > Can you explain the locking schema in this driver?
> >> >
> >> > > + /* Configure INT1 pin to open drain */
> >> > > + ret = regmap_write(data->regmap, BMA400_INT_IO_CTRL_REG,
> >> 0x06);
> >> > > + if (ret)
> >> > > + return ret;
> >> >
> >> > No locking (or regmap only locking).
> >>
> >> This is bma400_init() function which will run when probe runs so there is
> >> no
> >> locking in this bma400_init().
> >>
> >> >
> >> > ...
> >> >
> >> > > +static int bma400_data_rdy_trigger_set_state(struct iio_trigger
> >> *trig,
> >> > > + bool state)
> >> > > +{
> >> > > + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
> >> > > + struct bma400_data *data = iio_priv(indio_dev);
> >> > > + int ret;
> >> > > +
> >> > > + ret = regmap_update_bits(data->regmap,
> >> BMA400_INT_CONFIG0_REG,
> >> > > + BMA400_INT_DRDY_MSK,
> >> > > + FIELD_PREP(BMA400_INT_DRDY_MSK,
> >> state));
> >> > > + if (ret)
> >> > > + return ret;
> >> > > +
> >> > > + return regmap_update_bits(data->regmap, BMA400_INT1_MAP_REG,
> >> > > + BMA400_INT_DRDY_MSK,
> >> > > + FIELD_PREP(BMA400_INT_DRDY_MSK,
> >> state));
> >> > > +}
> >> >
> >> > Ditto.
> >>
> >> Sorry, I missed this.
> >> I will add lock and unlocking in the next patch.
> >>
> >> >
> >> > ...
> >> >
> >> > > + mutex_lock(&data->mutex);
> >> > > +
> >> > > + /* bulk read six registers, with the base being the LSB
> >> register */
> >> > > + ret = regmap_bulk_read(data->regmap, BMA400_X_AXIS_LSB_REG,
> >> > > + &data->buffer.buff,
> >> sizeof(data->buffer.buff));
> >> > > + mutex_unlock(&data->mutex);
> >> > > + if (ret)
> >> > > + return IRQ_NONE;
> >> >
> >> > But here only above with locking...
> >> >
> >> > > + ret = regmap_read(data->regmap, BMA400_TEMP_DATA_REG, &temp);
> >> > > + if (ret)
> >> > > + return IRQ_NONE;
> >> >
> >> > ...followed by no locking.
> >>
> >> Okay I will add lock in the next patch.
> >>
> >> >
> >> > ...
> >> >
> >> > > + mutex_lock(&data->mutex);
> >> > > + ret = regmap_bulk_read(data->regmap, BMA400_INT_STAT0_REG,
> >> &status,
> >> > > + sizeof(status));
> >> > > + mutex_unlock(&data->mutex);
> >> > > + if (ret)
> >> > > + return IRQ_NONE;
> >> >
> >> > And again with locking.
> >> >
> >> > ...
> >> >
> >> > So,
> >> > 1) Does regmap is configured with locking? What for?
> >> > 2) What's the role of data->mutex?
> >>
> >> 1.
> >> NO,
> >
> >
> > Are you sure?
> >
> >
> >> regmap is not configured with locking.
> >> In the remap_config structure variable below these members are not defined
> >> in the driver.
> >>
> >> struct regmap_config {
> >> regmap_lock lock;
> >> regmap_unlock unlock;
> >> void *lock_arg;
> >>
> >>
> > It means that default may be used.
> >
> >
> >> 2.
> >> data->mutex is used to protect the register read, write access from the
> >> device.
> >>
> >> Is the regmap functions handle locking and unlocking internally if these
> >> below
> >> struct members are not defined?
> >
> >
> > Yes. Look at this: https://elixir.bootlin.com/linux/latest/C/ident/
> > disable_locking
Please your advise will be very helpful for this.
I'm going through the same documentation. In this driver, disable_locking is
not initialized.
The functions which are called in the bma400_init() are not protected by mutex
for regmap since bma400_init() will run when the probe runs.
The functions which are called by read_raw() and write_raw() are protected by
mutex for regmap access.
There are some members in the device's private data structure and they are being
accessed in multiple places in the driver.
struct bma400_data {
enum bma400_power_mode power_mode;
struct bma400_sample_freq sample_freq;
int oversampling_ratio;
int scale;
.....
I think mutex is used to protect these above struct members since they are
critical resource, but in the struct bma400_data comment for mutex
is "data register lock".
> >
> >
> >>
> >> regmap_lock lock;
> >> regmap_unlock unlock;
> >> void *lock_arg;
> >>
> >>
> >> >
> >> > --
> >> > With Best Regards,
> >> > Andy Shevchenko
> >>
> >
> >>
>
> You may read the kernel documentation what those fields mean:
> https://elixir.bootlin.com/linux/latest/source/include/linux/regmap.h#L278
>
>
>
> > --
> > With Best Regards,
> > Andy Shevchenko
> >
> >
> >
>
> --
> With Best Regards,
> Andy Shevchenko
Thank you,
Jagath
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 4/9] iio: accel: bma400: Add triggered buffer support
2022-04-13 14:23 ` Jagath Jog J
@ 2022-04-14 13:22 ` Jagath Jog J
0 siblings, 0 replies; 30+ messages in thread
From: Jagath Jog J @ 2022-04-14 13:22 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Dan Robertson, Jonathan Cameron, linux-iio, Linux Kernel Mailing List
Hi Andy,
On Wed, Apr 13, 2022 at 07:53:46PM +0530, Jagath Jog J wrote:
> On Wed, Apr 13, 2022 at 12:24:54AM +0300, Andy Shevchenko wrote:
> > On Wednesday, April 13, 2022, Andy Shevchenko <andy.shevchenko@gmail.com>
> > wrote:
> >
> > >
> > >
> > > On Tuesday, April 12, 2022, Jagath Jog J <jagathjog1996@gmail.com> wrote:
> > >
> > >> Hello Andy,
> > >>
> > >> On Tue, Apr 12, 2022 at 12:12:21PM +0300, Andy Shevchenko wrote:
> > >> > On Mon, Apr 11, 2022 at 11:31 PM Jagath Jog J <jagathjog1996@gmail.com>
> > >> wrote:
> > >> > >
> > >> > > Added trigger buffer support to read continuous acceleration
> > >> > > data from device with data ready interrupt which is mapped
> > >> > > to INT1 pin.
> > >> >
> > >> > Can you explain the locking schema in this driver?
> > >> >
> > >> > > + /* Configure INT1 pin to open drain */
> > >> > > + ret = regmap_write(data->regmap, BMA400_INT_IO_CTRL_REG,
> > >> 0x06);
> > >> > > + if (ret)
> > >> > > + return ret;
> > >> >
> > >> > No locking (or regmap only locking).
> > >>
> > >> This is bma400_init() function which will run when probe runs so there is
> > >> no
> > >> locking in this bma400_init().
> > >>
> > >> >
> > >> > ...
> > >> >
> > >> > > +static int bma400_data_rdy_trigger_set_state(struct iio_trigger
> > >> *trig,
> > >> > > + bool state)
> > >> > > +{
> > >> > > + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
> > >> > > + struct bma400_data *data = iio_priv(indio_dev);
> > >> > > + int ret;
> > >> > > +
> > >> > > + ret = regmap_update_bits(data->regmap,
> > >> BMA400_INT_CONFIG0_REG,
> > >> > > + BMA400_INT_DRDY_MSK,
> > >> > > + FIELD_PREP(BMA400_INT_DRDY_MSK,
> > >> state));
> > >> > > + if (ret)
> > >> > > + return ret;
> > >> > > +
> > >> > > + return regmap_update_bits(data->regmap, BMA400_INT1_MAP_REG,
> > >> > > + BMA400_INT_DRDY_MSK,
> > >> > > + FIELD_PREP(BMA400_INT_DRDY_MSK,
> > >> state));
> > >> > > +}
> > >> >
> > >> > Ditto.
> > >>
> > >> Sorry, I missed this.
> > >> I will add lock and unlocking in the next patch.
> > >>
> > >> >
> > >> > ...
> > >> >
> > >> > > + mutex_lock(&data->mutex);
> > >> > > +
> > >> > > + /* bulk read six registers, with the base being the LSB
> > >> register */
> > >> > > + ret = regmap_bulk_read(data->regmap, BMA400_X_AXIS_LSB_REG,
> > >> > > + &data->buffer.buff,
> > >> sizeof(data->buffer.buff));
> > >> > > + mutex_unlock(&data->mutex);
> > >> > > + if (ret)
> > >> > > + return IRQ_NONE;
> > >> >
> > >> > But here only above with locking...
> > >> >
> > >> > > + ret = regmap_read(data->regmap, BMA400_TEMP_DATA_REG, &temp);
> > >> > > + if (ret)
> > >> > > + return IRQ_NONE;
> > >> >
> > >> > ...followed by no locking.
> > >>
> > >> Okay I will add lock in the next patch.
> > >>
> > >> >
> > >> > ...
> > >> >
> > >> > > + mutex_lock(&data->mutex);
> > >> > > + ret = regmap_bulk_read(data->regmap, BMA400_INT_STAT0_REG,
> > >> &status,
> > >> > > + sizeof(status));
> > >> > > + mutex_unlock(&data->mutex);
> > >> > > + if (ret)
> > >> > > + return IRQ_NONE;
> > >> >
> > >> > And again with locking.
> > >> >
> > >> > ...
> > >> >
> > >> > So,
> > >> > 1) Does regmap is configured with locking? What for?
> > >> > 2) What's the role of data->mutex?
> > >>
> > >> 1.
> > >> NO,
> > >
> > >
> > > Are you sure?
> > >
> > >
> > >> regmap is not configured with locking.
> > >> In the remap_config structure variable below these members are not defined
> > >> in the driver.
> > >>
> > >> struct regmap_config {
> > >> regmap_lock lock;
> > >> regmap_unlock unlock;
> > >> void *lock_arg;
> > >>
> > >>
> > > It means that default may be used.
> > >
> > >
> > >> 2.
> > >> data->mutex is used to protect the register read, write access from the
> > >> device.
> > >>
> > >> Is the regmap functions handle locking and unlocking internally if these
> > >> below
> > >> struct members are not defined?
> > >
> > >
> > > Yes. Look at this: https://elixir.bootlin.com/linux/latest/C/ident/
> > > disable_locking
>
> Please your advise will be very helpful for this.
>
> I'm going through the same documentation. In this driver, disable_locking is
> not initialized.
>
> The functions which are called in the bma400_init() are not protected by mutex
> for regmap since bma400_init() will run when the probe runs.
>
> The functions which are called by read_raw() and write_raw() are protected by
> mutex for regmap access.
>
> There are some members in the device's private data structure and they are being
> accessed in multiple places in the driver.
>
> struct bma400_data {
> enum bma400_power_mode power_mode;
> struct bma400_sample_freq sample_freq;
> int oversampling_ratio;
> int scale;
> .....
>
> I think mutex is used to protect these above struct members since they are
> critical resource, but in the struct bma400_data comment for mutex
> is "data register lock".
Sorry, I got my mistake about mutex lock and unlocking and I will correct those
in the next patch series.
Thank you
Jagath
>
>
> > >
> > >
> > >>
> > >> regmap_lock lock;
> > >> regmap_unlock unlock;
> > >> void *lock_arg;
> > >>
> > >>
> > >> >
> > >> > --
> > >> > With Best Regards,
> > >> > Andy Shevchenko
> > >>
> > >
> > >>
> >
> > You may read the kernel documentation what those fields mean:
> > https://elixir.bootlin.com/linux/latest/source/include/linux/regmap.h#L278
> >
> >
> >
> > > --
> > > With Best Regards,
> > > Andy Shevchenko
> > >
> > >
> > >
> >
> > --
> > With Best Regards,
> > Andy Shevchenko
>
> Thank you,
> Jagath
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 4/9] iio: accel: bma400: Add triggered buffer support
2022-04-11 20:31 ` [PATCH v3 4/9] iio: accel: bma400: Add triggered buffer support Jagath Jog J
2022-04-12 9:12 ` Andy Shevchenko
@ 2022-04-16 16:38 ` Jonathan Cameron
1 sibling, 0 replies; 30+ messages in thread
From: Jonathan Cameron @ 2022-04-16 16:38 UTC (permalink / raw)
To: Jagath Jog J; +Cc: dan, andy.shevchenko, linux-iio, linux-kernel
On Tue, 12 Apr 2022 02:01:28 +0530
Jagath Jog J <jagathjog1996@gmail.com> wrote:
> Added trigger buffer support to read continuous acceleration
> data from device with data ready interrupt which is mapped
> to INT1 pin.
>
> Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
A few comments inline.
Jonathan
> ---
> drivers/iio/accel/Kconfig | 2 +
> drivers/iio/accel/bma400.h | 10 ++-
> drivers/iio/accel/bma400_core.c | 153 ++++++++++++++++++++++++++++++--
> drivers/iio/accel/bma400_i2c.c | 2 +-
> drivers/iio/accel/bma400_spi.c | 2 +-
> 5 files changed, 161 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
> index eac3f02662ae..958097814232 100644
> --- a/drivers/iio/accel/Kconfig
> +++ b/drivers/iio/accel/Kconfig
> @@ -204,6 +204,8 @@ config BMA220
> config BMA400
> tristate "Bosch BMA400 3-Axis Accelerometer Driver"
> select REGMAP
> + select IIO_BUFFER
> + select IIO_TRIGGERED_BUFFER
> select BMA400_I2C if I2C
> select BMA400_SPI if SPI
> help
> diff --git a/drivers/iio/accel/bma400.h b/drivers/iio/accel/bma400.h
> index 8dbf85eeb005..a7482a66b36b 100644
> --- a/drivers/iio/accel/bma400.h
> +++ b/drivers/iio/accel/bma400.h
> @@ -62,6 +62,13 @@
> #define BMA400_ACC_CONFIG2_REG 0x1b
> #define BMA400_CMD_REG 0x7e
>
> +/* Interrupt registers */
> +#define BMA400_INT_CONFIG0_REG 0x1f
> +#define BMA400_INT_CONFIG1_REG 0x20
> +#define BMA400_INT1_MAP_REG 0x21
> +#define BMA400_INT_IO_CTRL_REG 0x24
> +#define BMA400_INT_DRDY_MSK BIT(7)
> +
> /* Chip ID of BMA 400 devices found in the chip ID register. */
> #define BMA400_ID_REG_VAL 0x90
>
> @@ -111,6 +118,7 @@
>
> extern const struct regmap_config bma400_regmap_config;
>
> -int bma400_probe(struct device *dev, struct regmap *regmap, const char *name);
> +int bma400_probe(struct device *dev, struct regmap *regmap, int irq,
> + const char *name);
>
> #endif
> diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
> index 07674d89d978..b7b2b67aef31 100644
> --- a/drivers/iio/accel/bma400_core.c
> +++ b/drivers/iio/accel/bma400_core.c
> @@ -11,6 +11,7 @@
> * - Create channel for sensor time
> */
>
> +#include <linux/bitfield.h>
> #include <linux/bitops.h>
> #include <linux/device.h>
> #include <linux/kernel.h>
> @@ -20,6 +21,10 @@
> #include <linux/regulator/consumer.h>
>
> #include <linux/iio/iio.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/trigger.h>
> +#include <linux/iio/trigger_consumer.h>
> +#include <linux/iio/triggered_buffer.h>
>
> #include "bma400.h"
>
> @@ -61,6 +66,13 @@ struct bma400_data {
> struct bma400_sample_freq sample_freq;
> int oversampling_ratio;
> int scale;
> + struct iio_trigger *trig;
> + /* Correct time stamp alignment */
> + struct {
> + __le16 buff[3];
> + u8 temperature;
> + s64 ts __aligned(8);
> + } buffer ____cacheline_aligned;
See below, but I'd suggest adding
__le16 status;
here to be in the same cacheline as the buffer and hence also DMA safe (as it's
not in the same line as anything else which could be modified concurrently.)
> };
>
> static bool bma400_is_writable_reg(struct device *dev, unsigned int reg)
> @@ -152,7 +164,7 @@ static const struct iio_chan_spec_ext_info bma400_ext_info[] = {
> { }
> };
>
> -#define BMA400_ACC_CHANNEL(_axis) { \
> +#define BMA400_ACC_CHANNEL(_index, _axis) { \
> .type = IIO_ACCEL, \
> .modified = 1, \
> .channel2 = IIO_MOD_##_axis, \
> @@ -164,17 +176,32 @@ static const struct iio_chan_spec_ext_info bma400_ext_info[] = {
> BIT(IIO_CHAN_INFO_SCALE) | \
> BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
> .ext_info = bma400_ext_info, \
> + .scan_index = _index, \
> + .scan_type = { \
> + .sign = 's', \
> + .realbits = 12, \
> + .storagebits = 16, \
> + .endianness = IIO_LE, \
> + }, \
> }
>
> static const struct iio_chan_spec bma400_channels[] = {
> - BMA400_ACC_CHANNEL(X),
> - BMA400_ACC_CHANNEL(Y),
> - BMA400_ACC_CHANNEL(Z),
> + BMA400_ACC_CHANNEL(0, X),
> + BMA400_ACC_CHANNEL(1, Y),
> + BMA400_ACC_CHANNEL(2, Z),
> {
> .type = IIO_TEMP,
> .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
> .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ),
> + .scan_index = 3,
> + .scan_type = {
> + .sign = 's',
> + .realbits = 8,
> + .storagebits = 8,
> + .endianness = IIO_LE,
> + },
> },
> + IIO_CHAN_SOFT_TIMESTAMP(4),
> };
>
> static int bma400_get_temp_reg(struct bma400_data *data, int *val, int *val2)
> @@ -659,6 +686,10 @@ static int bma400_init(struct bma400_data *data)
> if (ret)
> return ret;
>
> + /* Configure INT1 pin to open drain */
> + ret = regmap_write(data->regmap, BMA400_INT_IO_CTRL_REG, 0x06);
> + if (ret)
> + return ret;
> /*
> * Once the interrupt engine is supported we might use the
> * data_src_reg, but for now ensure this is set to the
> @@ -807,6 +838,29 @@ static int bma400_write_raw_get_fmt(struct iio_dev *indio_dev,
> }
> }
>
> +static int bma400_data_rdy_trigger_set_state(struct iio_trigger *trig,
> + bool state)
> +{
> + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
> + struct bma400_data *data = iio_priv(indio_dev);
> + int ret;
> +
> + ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG0_REG,
> + BMA400_INT_DRDY_MSK,
> + FIELD_PREP(BMA400_INT_DRDY_MSK, state));
> + if (ret)
> + return ret;
> +
> + return regmap_update_bits(data->regmap, BMA400_INT1_MAP_REG,
> + BMA400_INT_DRDY_MSK,
> + FIELD_PREP(BMA400_INT_DRDY_MSK, state));
> +}
> +
> +static const unsigned long bma400_avail_scan_masks[] = {
> + GENMASK(3, 0),
> + 0
> +};
> +
> static const struct iio_info bma400_info = {
> .read_raw = bma400_read_raw,
> .read_avail = bma400_read_avail,
> @@ -814,7 +868,64 @@ static const struct iio_info bma400_info = {
> .write_raw_get_fmt = bma400_write_raw_get_fmt,
> };
>
> -int bma400_probe(struct device *dev, struct regmap *regmap, const char *name)
> +static const struct iio_trigger_ops bma400_trigger_ops = {
> + .set_trigger_state = &bma400_data_rdy_trigger_set_state,
> + .validate_device = &iio_trigger_validate_own_device,
> +};
> +
> +static irqreturn_t bma400_trigger_handler(int irq, void *p)
> +{
> + struct iio_poll_func *pf = p;
> + struct iio_dev *indio_dev = pf->indio_dev;
> + struct bma400_data *data = iio_priv(indio_dev);
> + int ret, temp;
> +
> + mutex_lock(&data->mutex);
> +
> + /* bulk read six registers, with the base being the LSB register */
> + ret = regmap_bulk_read(data->regmap, BMA400_X_AXIS_LSB_REG,
> + &data->buffer.buff, sizeof(data->buffer.buff));
> + mutex_unlock(&data->mutex);
> + if (ret)
> + return IRQ_NONE;
> +
> + ret = regmap_read(data->regmap, BMA400_TEMP_DATA_REG, &temp);
> + if (ret)
> + return IRQ_NONE;
> +
> + data->buffer.temperature = temp;
> +
> + iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer,
> + iio_get_time_ns(indio_dev));
> +
> + iio_trigger_notify_done(indio_dev->trig);
> + return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t bma400_interrupt(int irq, void *private)
> +{
> + struct iio_dev *indio_dev = private;
> + struct bma400_data *data = iio_priv(indio_dev);
> + int ret;
> + __le16 status;
> +
> + mutex_lock(&data->mutex);
> + ret = regmap_bulk_read(data->regmap, BMA400_INT_STAT0_REG, &status,
> + sizeof(status));
regmap_bulk_read() (may) need a DMA safe buffer. Which means you can't use
a variable on the stack. Look at using the carefully aligned and padded
data->buffer if you can as that is DMA safe.
Note that then you will need that lock as it protects that buffer...
You could also just add a suitable buffer after that instead
of reusing that particular structure.
> + mutex_unlock(&data->mutex);
> + if (ret)
> + return IRQ_NONE;
> +
> + if (FIELD_GET(BMA400_INT_DRDY_MSK, le16_to_cpu(status))) {
> + iio_trigger_poll_chained(data->trig);
> + return IRQ_HANDLED;
> + }
> +
> + return IRQ_NONE;
> +}
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 5/9] iio: accel: bma400: Add separate channel for step counter
2022-04-11 20:31 ` [PATCH v3 5/9] iio: accel: bma400: Add separate channel for step counter Jagath Jog J
@ 2022-04-16 16:41 ` Jonathan Cameron
0 siblings, 0 replies; 30+ messages in thread
From: Jonathan Cameron @ 2022-04-16 16:41 UTC (permalink / raw)
To: Jagath Jog J; +Cc: dan, andy.shevchenko, linux-iio, linux-kernel
On Tue, 12 Apr 2022 02:01:29 +0530
Jagath Jog J <jagathjog1996@gmail.com> wrote:
> Added channel for step counter which can be enable or disable
> through the sysfs interface.
>
> Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
> ---
> drivers/iio/accel/bma400.h | 1 +
> drivers/iio/accel/bma400_core.c | 48 ++++++++++++++++++++++++++++++---
> 2 files changed, 45 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/iio/accel/bma400.h b/drivers/iio/accel/bma400.h
> index a7482a66b36b..52f9ea95de81 100644
> --- a/drivers/iio/accel/bma400.h
> +++ b/drivers/iio/accel/bma400.h
> @@ -53,6 +53,7 @@
> #define BMA400_STEP_CNT1_REG 0x16
> #define BMA400_STEP_CNT3_REG 0x17
> #define BMA400_STEP_STAT_REG 0x18
> +#define BMA400_STEP_INT_MSK BIT(0)
>
> /*
> * Read-write configuration registers
> diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
> index b7b2b67aef31..c8f147163d3c 100644
> --- a/drivers/iio/accel/bma400_core.c
> +++ b/drivers/iio/accel/bma400_core.c
> @@ -20,6 +20,8 @@
> #include <linux/regmap.h>
> #include <linux/regulator/consumer.h>
>
> +#include <asm/unaligned.h>
> +
> #include <linux/iio/iio.h>
> #include <linux/iio/buffer.h>
> #include <linux/iio/trigger.h>
> @@ -67,6 +69,7 @@ struct bma400_data {
> int oversampling_ratio;
> int scale;
> struct iio_trigger *trig;
> + int steps_enabled;
> /* Correct time stamp alignment */
> struct {
> __le16 buff[3];
> @@ -201,6 +204,12 @@ static const struct iio_chan_spec bma400_channels[] = {
> .endianness = IIO_LE,
> },
> },
> + {
> + .type = IIO_STEPS,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
> + BIT(IIO_CHAN_INFO_ENABLE),
> + .scan_index = -1, /* No buffer support */
> + },
> IIO_CHAN_SOFT_TIMESTAMP(4),
> };
>
> @@ -705,13 +714,28 @@ static int bma400_read_raw(struct iio_dev *indio_dev,
> {
> struct bma400_data *data = iio_priv(indio_dev);
> int ret;
> + u8 steps_raw[3];
>
> switch (mask) {
> case IIO_CHAN_INFO_PROCESSED:
> - mutex_lock(&data->mutex);
> - ret = bma400_get_temp_reg(data, val, val2);
> - mutex_unlock(&data->mutex);
> - return ret;
> + switch (chan->type) {
> + case IIO_TEMP:
> + mutex_lock(&data->mutex);
> + ret = bma400_get_temp_reg(data, val, val2);
> + mutex_unlock(&data->mutex);
> + return ret;
> + case IIO_STEPS:
> + mutex_lock(&data->mutex);
> + ret = regmap_bulk_read(data->regmap, BMA400_STEP_CNT0_REG,
> + &steps_raw, sizeof(steps_raw));
Bulk read to a non DMA safe buffer. Similar fix to before needed.
Or given this is a slow path, just use a local kmalloc() for the buffer.
The reality is you are probably fine today without such care, but last
time we discussed this the conclusion was that it would be a perfectly
valid optimisation in regmap to return to requiring DMA safe buffers
for bulk accesses.
> + mutex_unlock(&data->mutex);
> + if (ret)
> + return ret;
> + *val = get_unaligned_le24(steps_raw);
> + return IIO_VAL_INT;
> + default:
> + return -EINVAL;
> + }
> case IIO_CHAN_INFO_RAW:
> mutex_lock(&data->mutex);
> ret = bma400_get_accel_reg(data, chan, val);
> @@ -752,6 +776,9 @@ static int bma400_read_raw(struct iio_dev *indio_dev,
>
> *val = data->oversampling_ratio;
> return IIO_VAL_INT;
> + case IIO_CHAN_INFO_ENABLE:
> + *val = data->steps_enabled;
> + return IIO_VAL_INT;
> default:
> return -EINVAL;
> }
> @@ -817,6 +844,17 @@ static int bma400_write_raw(struct iio_dev *indio_dev,
> ret = bma400_set_accel_oversampling_ratio(data, val);
> mutex_unlock(&data->mutex);
> return ret;
> + case IIO_CHAN_INFO_ENABLE:
> + if (data->steps_enabled == val)
> + return 0;
> +
> + mutex_lock(&data->mutex);
> + ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG1_REG,
> + BMA400_STEP_INT_MSK,
> + FIELD_PREP(BMA400_STEP_INT_MSK, !!val));
Why the lock for this one?
> + mutex_unlock(&data->mutex);
> + data->steps_enabled = val;
> + return ret;
> default:
> return -EINVAL;
> }
> @@ -833,6 +871,8 @@ static int bma400_write_raw_get_fmt(struct iio_dev *indio_dev,
> return IIO_VAL_INT_PLUS_MICRO;
> case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
> return IIO_VAL_INT;
> + case IIO_CHAN_INFO_ENABLE:
> + return IIO_VAL_INT;
> default:
> return -EINVAL;
> }
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 7/9] iio: accel: bma400: Add activity recognition support
2022-04-11 20:31 ` [PATCH v3 7/9] iio: accel: bma400: Add activity recognition support Jagath Jog J
@ 2022-04-16 16:47 ` Jonathan Cameron
0 siblings, 0 replies; 30+ messages in thread
From: Jonathan Cameron @ 2022-04-16 16:47 UTC (permalink / raw)
To: Jagath Jog J; +Cc: dan, andy.shevchenko, linux-iio, linux-kernel
On Tue, 12 Apr 2022 02:01:31 +0530
Jagath Jog J <jagathjog1996@gmail.com> wrote:
> Add support for activity recognition like STILL, WALKING, RUNNING
> and these events are pushed to the userspace whenever the STEP
> interrupt occurs.
>
> Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
Hi Jagath,
Other than more questions on locking and a suggestion for some
code deduplication this looks good to me.
Jonathan
> ---
> drivers/iio/accel/bma400_core.c | 104 ++++++++++++++++++++++++++++++++
> 1 file changed, 104 insertions(+)
>
> diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
> index 37f38626a9aa..69d2caa4ed18 100644
> --- a/drivers/iio/accel/bma400_core.c
> +++ b/drivers/iio/accel/bma400_core.c
> @@ -59,6 +59,12 @@ struct bma400_sample_freq {
> int uhz;
> };
>
> +enum bma400_activity {
> + BMA400_STILL,
> + BMA400_WALKING,
> + BMA400_RUNNING,
> +};
> +
> struct bma400_data {
> struct device *dev;
> struct regmap *regmap;
> @@ -72,6 +78,7 @@ struct bma400_data {
> struct iio_trigger *trig;
> int steps_enabled;
> bool step_event_en;
> + bool activity_event_en;
> /* Correct time stamp alignment */
> struct {
> __le16 buff[3];
> @@ -175,6 +182,12 @@ static const struct iio_event_spec bma400_step_detect_event = {
> .mask_separate = BIT(IIO_EV_INFO_ENABLE),
> };
>
> +static const struct iio_event_spec bma400_activity_event = {
> + .type = IIO_EV_TYPE_CHANGE,
> + .dir = IIO_EV_DIR_NONE,
> + .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE),
> +};
> +
> #define BMA400_ACC_CHANNEL(_index, _axis) { \
> .type = IIO_ACCEL, \
> .modified = 1, \
> @@ -196,6 +209,16 @@ static const struct iio_event_spec bma400_step_detect_event = {
> }, \
> }
>
> +#define BMA400_ACTIVITY_CHANNEL(_chan2) { \
> + .type = IIO_ACTIVITY, \
> + .modified = 1, \
> + .channel2 = _chan2, \
> + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
> + .scan_index = -1, /* No buffer support */ \
> + .event_spec = &bma400_activity_event, \
> + .num_event_specs = 1, \
> +}
> +
> static const struct iio_chan_spec bma400_channels[] = {
> BMA400_ACC_CHANNEL(0, X),
> BMA400_ACC_CHANNEL(1, Y),
> @@ -220,6 +243,9 @@ static const struct iio_chan_spec bma400_channels[] = {
> .event_spec = &bma400_step_detect_event,
> .num_event_specs = 1,
> },
> + BMA400_ACTIVITY_CHANNEL(IIO_MOD_STILL),
> + BMA400_ACTIVITY_CHANNEL(IIO_MOD_WALKING),
> + BMA400_ACTIVITY_CHANNEL(IIO_MOD_RUNNING),
> IIO_CHAN_SOFT_TIMESTAMP(4),
> };
>
> @@ -626,6 +652,20 @@ static void bma400_power_disable(void *data_ptr)
> ERR_PTR(ret));
> }
>
> +static enum iio_modifier bma400_act_to_mod(enum bma400_activity activity)
> +{
> + switch (activity) {
> + case BMA400_STILL:
> + return IIO_MOD_STILL;
> + case BMA400_WALKING:
> + return IIO_MOD_WALKING;
> + case BMA400_RUNNING:
> + return IIO_MOD_RUNNING;
> + default:
> + return IIO_NO_MOD;
> + }
> +}
> +
> static int bma400_init(struct bma400_data *data)
> {
> unsigned int val;
> @@ -725,6 +765,7 @@ static int bma400_read_raw(struct iio_dev *indio_dev,
> struct bma400_data *data = iio_priv(indio_dev);
> int ret;
> u8 steps_raw[3];
> + unsigned int activity;
>
> switch (mask) {
> case IIO_CHAN_INFO_PROCESSED:
> @@ -743,6 +784,23 @@ static int bma400_read_raw(struct iio_dev *indio_dev,
> return ret;
> *val = get_unaligned_le24(steps_raw);
> return IIO_VAL_INT;
> + case IIO_ACTIVITY:
> + mutex_lock(&data->mutex);
> + ret = regmap_read(data->regmap, BMA400_STEP_STAT_REG,
> + &activity);
More locking in here to think about. Not clear what you are protecting here.
> + mutex_unlock(&data->mutex);
> + if (ret)
> + return ret;
> + /*
> + * The device does not support confidence value levels,
> + * so we will always have 100% for current activity and
> + * 0% for the others.
I was thinking ahead when I came up with confidence for these. One day someone
will implement a sensor that is honest that it isn't that sure what the activity is.
:) When they do we'll be ready!
> + */
> + if (chan->channel2 == bma400_act_to_mod(activity))
> + *val = 100;
> + else
> + *val = 0;
> + return IIO_VAL_INT;
> default:
> return -EINVAL;
> }
> @@ -898,6 +956,8 @@ static int bma400_read_event_config(struct iio_dev *indio_dev,
> switch (chan->type) {
> case IIO_STEPS:
> return data->step_event_en;
> + case IIO_ACTIVITY:
> + return data->activity_event_en;
> default:
> return -EINVAL;
> }
> @@ -937,6 +997,32 @@ static int bma400_write_event_config(struct iio_dev *indio_dev,
> return ret;
> data->step_event_en = state;
> return 0;
> + case IIO_ACTIVITY:
> + if (!data->step_event_en) {
> + mutex_lock(&data->mutex);
> + ret = regmap_update_bits(data->regmap,
> + BMA400_INT_CONFIG1_REG,
> + BMA400_STEP_INT_MSK,
> + FIELD_PREP(BMA400_STEP_INT_MSK,
> + 1));
> + if (ret) {
> + mutex_unlock(&data->mutex);
> + return ret;
> + }
> + data->steps_enabled = 1;
> +
> + ret = regmap_update_bits(data->regmap,
> + BMA400_INT12_MAP_REG,
> + BMA400_STEP_INT_MSK,
> + FIELD_PREP(BMA400_STEP_INT_MSK,
> + 1));
This looks like some code that could be sensibly factored out in the earlier
patch to provide a function to call here rather than having another copy
of more or less the same code.
> + mutex_unlock(&data->mutex);
> + if (ret)
> + return ret;
> + data->step_event_en = 1;
I can understand logic of using lock to keep the internal tracking in sync
with the device, but here you are doing that outside the lock which doesn't seem
to do that.
> + }
> + data->activity_event_en = state;
> + return 0;
> default:
> return -EINVAL;
> }
> @@ -1015,6 +1101,7 @@ static irqreturn_t bma400_interrupt(int irq, void *private)
> s64 timestamp = iio_get_time_ns(indio_dev);
> int ret;
> __le16 status;
> + unsigned int act;
>
> mutex_lock(&data->mutex);
> ret = regmap_bulk_read(data->regmap, BMA400_INT_STAT0_REG, &status,
> @@ -1029,6 +1116,23 @@ static irqreturn_t bma400_interrupt(int irq, void *private)
> IIO_EV_DIR_NONE,
> IIO_EV_TYPE_CHANGE, 0, 0, 0),
> timestamp);
> +
> + if (data->activity_event_en) {
> + mutex_lock(&data->mutex);
> + ret = regmap_read(data->regmap, BMA400_STEP_STAT_REG,
> + &act);
> + mutex_unlock(&data->mutex);
> + if (ret)
> + return IRQ_NONE;
> +
> + iio_push_event(indio_dev,
> + IIO_EVENT_CODE(IIO_ACTIVITY, 0,
> + bma400_act_to_mod(act),
> + IIO_EV_DIR_NONE,
> + IIO_EV_TYPE_CHANGE, 0,
> + 0, 0),
> + timestamp);
> + }
> return IRQ_HANDLED;
> }
>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 8/9] iio: accel: bma400: Add debugfs register access support
2022-04-11 20:31 ` [PATCH v3 8/9] iio: accel: bma400: Add debugfs register access support Jagath Jog J
@ 2022-04-16 16:48 ` Jonathan Cameron
0 siblings, 0 replies; 30+ messages in thread
From: Jonathan Cameron @ 2022-04-16 16:48 UTC (permalink / raw)
To: Jagath Jog J; +Cc: dan, andy.shevchenko, linux-iio, linux-kernel
On Tue, 12 Apr 2022 02:01:32 +0530
Jagath Jog J <jagathjog1996@gmail.com> wrote:
> Add support to read/write byte from/to bma400 device from the userspace
> using debugfs interface.
>
> Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
> ---
> drivers/iio/accel/bma400_core.c | 18 ++++++++++++++++++
> 1 file changed, 18 insertions(+)
>
> diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
> index 69d2caa4ed18..b6c79cfabaa4 100644
> --- a/drivers/iio/accel/bma400_core.c
> +++ b/drivers/iio/accel/bma400_core.c
> @@ -1028,6 +1028,23 @@ static int bma400_write_event_config(struct iio_dev *indio_dev,
> }
> }
>
> +static int bma400_debugfs_reg_access(struct iio_dev *indio_dev,
> + unsigned int reg,
> + unsigned int writeval,
> + unsigned int *readval)
> +{
> + struct bma400_data *data = iio_priv(indio_dev);
> + int ret;
> +
> + mutex_lock(&data->mutex);
Guess what? :) Can't see what purpose locking this has.
> + if (readval)
> + ret = regmap_read(data->regmap, reg, readval);
> + else
> + ret = regmap_write(data->regmap, reg, writeval);
> + mutex_unlock(&data->mutex);
> + return ret;
> +}
> +
> static int bma400_data_rdy_trigger_set_state(struct iio_trigger *trig,
> bool state)
> {
> @@ -1058,6 +1075,7 @@ static const struct iio_info bma400_info = {
> .write_raw_get_fmt = bma400_write_raw_get_fmt,
> .read_event_config = bma400_read_event_config,
> .write_event_config = bma400_write_event_config,
> + .debugfs_reg_access = bma400_debugfs_reg_access,
> };
>
> static const struct iio_trigger_ops bma400_trigger_ops = {
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 9/9] iio: accel: bma400: Add support for activity and inactivity events
2022-04-11 20:31 ` [PATCH v3 9/9] iio: accel: bma400: Add support for activity and inactivity events Jagath Jog J
2022-04-12 5:21 ` kernel test robot
2022-04-12 10:41 ` kernel test robot
@ 2022-04-16 16:55 ` Jonathan Cameron
2022-04-18 22:09 ` Jagath Jog J
2 siblings, 1 reply; 30+ messages in thread
From: Jonathan Cameron @ 2022-04-16 16:55 UTC (permalink / raw)
To: Jagath Jog J; +Cc: dan, andy.shevchenko, linux-iio, linux-kernel
On Tue, 12 Apr 2022 02:01:33 +0530
Jagath Jog J <jagathjog1996@gmail.com> wrote:
> Add support for activity and inactivity events for all axis based on the
> threshold, duration and hysteresis value set from the userspace. INT1 pin
> is used to interrupt and event is pushed to userspace.
>
> Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
> ---
> drivers/iio/accel/bma400.h | 11 ++
> drivers/iio/accel/bma400_core.c | 229 ++++++++++++++++++++++++++++++++
> 2 files changed, 240 insertions(+)
>
> diff --git a/drivers/iio/accel/bma400.h b/drivers/iio/accel/bma400.h
> index bc4641279be3..cbf8035c817e 100644
> --- a/drivers/iio/accel/bma400.h
> +++ b/drivers/iio/accel/bma400.h
> @@ -93,6 +93,17 @@
> #define BMA400_ACC_ODR_MIN_WHOLE_HZ 25
> #define BMA400_ACC_ODR_MIN_HZ 12
>
> +/* Generic interrupts register */
> +#define BMA400_GEN1INT_CONFIG0 0x3f
> +#define BMA400_GEN2INT_CONFIG0 0x4A
> +#define BMA400_GEN_CONFIG1_OFF 0x01
> +#define BMA400_GEN_CONFIG2_OFF 0x02
> +#define BMA400_GEN_CONFIG3_OFF 0x03
> +#define BMA400_GEN_CONFIG31_OFF 0x04
> +#define BMA400_INT_GEN1_MSK BIT(2)
> +#define BMA400_INT_GEN2_MSK BIT(3)
> +#define BMA400_GEN_HYST_MSK GENMASK(1, 0)
> +
> /*
> * BMA400_SCALE_MIN macro value represents m/s^2 for 1 LSB before
> * converting to micro values for +-2g range.
> diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
> index b6c79cfabaa4..226a5f63d1a6 100644
> --- a/drivers/iio/accel/bma400_core.c
> +++ b/drivers/iio/accel/bma400_core.c
> @@ -79,6 +79,7 @@ struct bma400_data {
> int steps_enabled;
> bool step_event_en;
> bool activity_event_en;
> + u8 generic_event_en;
> /* Correct time stamp alignment */
> struct {
> __le16 buff[3];
> @@ -188,6 +189,25 @@ static const struct iio_event_spec bma400_activity_event = {
> .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE),
> };
>
> +static const struct iio_event_spec bma400_accel_event[] = {
> + {
> + .type = IIO_EV_TYPE_MAG,
> + .dir = IIO_EV_DIR_FALLING,
> + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
> + BIT(IIO_EV_INFO_PERIOD) |
> + BIT(IIO_EV_INFO_HYSTERESIS) |
> + BIT(IIO_EV_INFO_ENABLE),
> + },
> + {
> + .type = IIO_EV_TYPE_MAG,
> + .dir = IIO_EV_DIR_RISING,
> + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
> + BIT(IIO_EV_INFO_PERIOD) |
> + BIT(IIO_EV_INFO_HYSTERESIS) |
> + BIT(IIO_EV_INFO_ENABLE),
> + },
> +};
> +
> #define BMA400_ACC_CHANNEL(_index, _axis) { \
> .type = IIO_ACCEL, \
> .modified = 1, \
> @@ -207,6 +227,8 @@ static const struct iio_event_spec bma400_activity_event = {
> .storagebits = 16, \
> .endianness = IIO_LE, \
> }, \
> + .event_spec = bma400_accel_event, \
> + .num_event_specs = ARRAY_SIZE(bma400_accel_event) \
> }
>
> #define BMA400_ACTIVITY_CHANNEL(_chan2) { \
> @@ -954,6 +976,17 @@ static int bma400_read_event_config(struct iio_dev *indio_dev,
> struct bma400_data *data = iio_priv(indio_dev);
>
> switch (chan->type) {
> + case IIO_ACCEL:
> + switch (dir) {
> + case IIO_EV_DIR_RISING:
> + return FIELD_GET(BMA400_INT_GEN1_MSK,
> + data->generic_event_en);
> + case IIO_EV_DIR_FALLING:
> + return FIELD_GET(BMA400_INT_GEN2_MSK,
> + data->generic_event_en);
> + default:
> + return -EINVAL;
> + }
> case IIO_STEPS:
> return data->step_event_en;
> case IIO_ACTIVITY:
> @@ -970,8 +1003,74 @@ static int bma400_write_event_config(struct iio_dev *indio_dev,
> {
> int ret;
> struct bma400_data *data = iio_priv(indio_dev);
> + int reg, msk, value, field_value;
>
> switch (chan->type) {
> + case IIO_ACCEL:
> + switch (dir) {
> + case IIO_EV_DIR_RISING:
> + reg = BMA400_GEN1INT_CONFIG0;
> + msk = BMA400_INT_GEN1_MSK;
> + value = 2;
> + field_value = FIELD_PREP(BMA400_INT_GEN1_MSK, state);
Hopefully you can use msk in here and the compiler can tell it's constant...
> + break;
> + case IIO_EV_DIR_FALLING:
> + reg = BMA400_GEN2INT_CONFIG0;
> + msk = BMA400_INT_GEN2_MSK;
> + value = 0;
> + field_value = FIELD_PREP(BMA400_INT_GEN2_MSK, state);
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + mutex_lock(&data->mutex);
> + /* Enabling all axis for interrupt evaluation */
> + ret = regmap_write(data->regmap, reg, 0xF8);
> + if (ret) {
> + mutex_unlock(&data->mutex);
> + return ret;
> + }
> +
> + /* OR combination of all axis for interrupt evaluation */
> + ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG1_OFF,
> + value);
> + if (ret) {
> + mutex_unlock(&data->mutex);
> + return ret;
> + }
> +
> + /* Initial value to avoid interrupts while enabling*/
> + ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
> + 0x0A);
> + if (ret) {
> + mutex_unlock(&data->mutex);
> + return ret;
> + }
> +
> + /* Initial duration value to avoid interrupts while enabling*/
> + ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG31_OFF,
> + 0x0F);
> + if (ret) {
> + mutex_unlock(&data->mutex);
> + return ret;
> + }
> +
> + ret = regmap_update_bits(data->regmap, BMA400_INT1_MAP_REG,
> + msk, field_value);
> + if (ret) {
> + mutex_unlock(&data->mutex);
> + return ret;
> + }
> +
> + ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG0_REG,
> + msk, field_value);
> + mutex_unlock(&data->mutex);
> + if (ret)
> + return ret;
This whole stack or mutex_unlock() error handling is a good hint that you should
just factor out this case as a separate function then you can use a goto to
deal with the unlock cleanly.
> +
> + set_mask_bits(&data->generic_event_en, msk, field_value);
> + return 0;
> case IIO_STEPS:
> mutex_lock(&data->mutex);
> if (!data->steps_enabled) {
> @@ -1028,6 +1127,118 @@ static int bma400_write_event_config(struct iio_dev *indio_dev,
> }
> }
>
> +static int get_gen_config_reg(enum iio_event_direction dir)
> +{
> + switch (dir) {
> + case IIO_EV_DIR_FALLING:
> + return BMA400_GEN2INT_CONFIG0;
> + case IIO_EV_DIR_RISING:
> + return BMA400_GEN1INT_CONFIG0;
> + default:
> + return -EINVAL;
> + }
> +}
> +
> +static int bma400_read_event_value(struct iio_dev *indio_dev,
> + const struct iio_chan_spec *chan,
> + enum iio_event_type type,
> + enum iio_event_direction dir,
> + enum iio_event_info info,
> + int *val, int *val2)
> +{
> + struct bma400_data *data = iio_priv(indio_dev);
> + int ret;
> + u8 reg, duration[2];
> +
> + reg = get_gen_config_reg(dir);
> + if (reg < 0)
> + return -EINVAL;
> +
> + *val2 = 0;
> + switch (info) {
> + case IIO_EV_INFO_VALUE:
> + mutex_lock(&data->mutex);
> + ret = regmap_read(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
> + val);
> + mutex_unlock(&data->mutex);
> + if (ret)
> + return ret;
> + return IIO_VAL_INT;
> + case IIO_EV_INFO_PERIOD:
> + mutex_lock(&data->mutex);
> + ret = regmap_bulk_read(data->regmap,
> + reg + BMA400_GEN_CONFIG3_OFF,
> + duration, sizeof(duration));
> + mutex_unlock(&data->mutex);
> + if (ret)
> + return ret;
> + *val = get_unaligned_be16(duration);
As well as dma safety question, you could just have used a __be16 for
duration then you can use be16_to_cpu() as you know it is aligned.
> + return IIO_VAL_INT;
> + case IIO_EV_INFO_HYSTERESIS:
> + mutex_lock(&data->mutex);
> + ret = regmap_read(data->regmap, reg, val);
> + mutex_unlock(&data->mutex);
> + if (ret)
> + return ret;
> + *val = FIELD_GET(BMA400_GEN_HYST_MSK, *val);
> + return IIO_VAL_INT;
> + default:
> + return -EINVAL;
> + }
> +}
> +
> +static int bma400_write_event_value(struct iio_dev *indio_dev,
> + const struct iio_chan_spec *chan,
> + enum iio_event_type type,
> + enum iio_event_direction dir,
> + enum iio_event_info info,
> + int val, int val2)
> +{
> + struct bma400_data *data = iio_priv(indio_dev);
> + int ret;
> + u8 reg, duration[2];
> +
> + reg = get_gen_config_reg(dir);
> + if (reg < 0)
> + return -EINVAL;
> +
> + switch (info) {
> + case IIO_EV_INFO_VALUE:
> + if (val < 1 || val > 255)
> + return -EINVAL;
> +
> + mutex_lock(&data->mutex);
> + ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
> + val);
> + mutex_unlock(&data->mutex);
> + return ret;
> + case IIO_EV_INFO_PERIOD:
> + if (val < 1 || val > 65535)
> + return -EINVAL;
> +
> + put_unaligned_be16(val, duration);
> +
> + mutex_lock(&data->mutex);
> + ret = regmap_bulk_write(data->regmap,
> + reg + BMA400_GEN_CONFIG3_OFF,
> + duration, sizeof(duration));
I can't remember if we are safe or not with bulk_writes but at least
in theory we might not be and should be using a dma safe buffer.
Also locking not necessary in various places in here.
> + mutex_unlock(&data->mutex);
> + return ret;
> + case IIO_EV_INFO_HYSTERESIS:
> + if (val < 0 || val > 3)
> + return -EINVAL;
> +
> + mutex_lock(&data->mutex);
> + ret = regmap_update_bits(data->regmap, reg,
> + BMA400_GEN_HYST_MSK,
> + FIELD_PREP(BMA400_GEN_HYST_MSK, val));
> + mutex_unlock(&data->mutex);
> + return ret;
> + default:
> + return -EINVAL;
> + }
> +}
> +
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 9/9] iio: accel: bma400: Add support for activity and inactivity events
2022-04-16 16:55 ` Jonathan Cameron
@ 2022-04-18 22:09 ` Jagath Jog J
2022-04-24 15:40 ` Jonathan Cameron
0 siblings, 1 reply; 30+ messages in thread
From: Jagath Jog J @ 2022-04-18 22:09 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: dan, andy.shevchenko, linux-iio, linux-kernel
Hello Jonathan,
Thanks for your suggestions, I will fix the locking and unlocking for all
patches in the next series.
Please can you guide me for auto build test error reported by kernel test
robot for set_mask_bits(&data->generic_event_en, msk, field_value);
in this patch.
On Sat, Apr 16, 2022 at 05:55:37PM +0100, Jonathan Cameron wrote:
> On Tue, 12 Apr 2022 02:01:33 +0530
> Jagath Jog J <jagathjog1996@gmail.com> wrote:
>
> > Add support for activity and inactivity events for all axis based on the
> > threshold, duration and hysteresis value set from the userspace. INT1 pin
> > is used to interrupt and event is pushed to userspace.
> >
> > Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
> > ---
> > drivers/iio/accel/bma400.h | 11 ++
> > drivers/iio/accel/bma400_core.c | 229 ++++++++++++++++++++++++++++++++
> > 2 files changed, 240 insertions(+)
> >
> > diff --git a/drivers/iio/accel/bma400.h b/drivers/iio/accel/bma400.h
> > index bc4641279be3..cbf8035c817e 100644
> > --- a/drivers/iio/accel/bma400.h
> > +++ b/drivers/iio/accel/bma400.h
> > @@ -93,6 +93,17 @@
> > #define BMA400_ACC_ODR_MIN_WHOLE_HZ 25
> > #define BMA400_ACC_ODR_MIN_HZ 12
> >
> > +/* Generic interrupts register */
> > +#define BMA400_GEN1INT_CONFIG0 0x3f
> > +#define BMA400_GEN2INT_CONFIG0 0x4A
> > +#define BMA400_GEN_CONFIG1_OFF 0x01
> > +#define BMA400_GEN_CONFIG2_OFF 0x02
> > +#define BMA400_GEN_CONFIG3_OFF 0x03
> > +#define BMA400_GEN_CONFIG31_OFF 0x04
> > +#define BMA400_INT_GEN1_MSK BIT(2)
> > +#define BMA400_INT_GEN2_MSK BIT(3)
> > +#define BMA400_GEN_HYST_MSK GENMASK(1, 0)
> > +
> > /*
> > * BMA400_SCALE_MIN macro value represents m/s^2 for 1 LSB before
> > * converting to micro values for +-2g range.
> > diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
> > index b6c79cfabaa4..226a5f63d1a6 100644
> > --- a/drivers/iio/accel/bma400_core.c
> > +++ b/drivers/iio/accel/bma400_core.c
> > @@ -79,6 +79,7 @@ struct bma400_data {
> > int steps_enabled;
> > bool step_event_en;
> > bool activity_event_en;
> > + u8 generic_event_en;
> > /* Correct time stamp alignment */
> > struct {
> > __le16 buff[3];
> > @@ -188,6 +189,25 @@ static const struct iio_event_spec bma400_activity_event = {
> > .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE),
> > };
> >
> > +static const struct iio_event_spec bma400_accel_event[] = {
> > + {
> > + .type = IIO_EV_TYPE_MAG,
> > + .dir = IIO_EV_DIR_FALLING,
> > + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
> > + BIT(IIO_EV_INFO_PERIOD) |
> > + BIT(IIO_EV_INFO_HYSTERESIS) |
> > + BIT(IIO_EV_INFO_ENABLE),
> > + },
> > + {
> > + .type = IIO_EV_TYPE_MAG,
> > + .dir = IIO_EV_DIR_RISING,
> > + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
> > + BIT(IIO_EV_INFO_PERIOD) |
> > + BIT(IIO_EV_INFO_HYSTERESIS) |
> > + BIT(IIO_EV_INFO_ENABLE),
> > + },
> > +};
> > +
> > #define BMA400_ACC_CHANNEL(_index, _axis) { \
> > .type = IIO_ACCEL, \
> > .modified = 1, \
> > @@ -207,6 +227,8 @@ static const struct iio_event_spec bma400_activity_event = {
> > .storagebits = 16, \
> > .endianness = IIO_LE, \
> > }, \
> > + .event_spec = bma400_accel_event, \
> > + .num_event_specs = ARRAY_SIZE(bma400_accel_event) \
> > }
> >
> > #define BMA400_ACTIVITY_CHANNEL(_chan2) { \
> > @@ -954,6 +976,17 @@ static int bma400_read_event_config(struct iio_dev *indio_dev,
> > struct bma400_data *data = iio_priv(indio_dev);
> >
> > switch (chan->type) {
> > + case IIO_ACCEL:
> > + switch (dir) {
> > + case IIO_EV_DIR_RISING:
> > + return FIELD_GET(BMA400_INT_GEN1_MSK,
> > + data->generic_event_en);
> > + case IIO_EV_DIR_FALLING:
> > + return FIELD_GET(BMA400_INT_GEN2_MSK,
> > + data->generic_event_en);
> > + default:
> > + return -EINVAL;
> > + }
> > case IIO_STEPS:
> > return data->step_event_en;
> > case IIO_ACTIVITY:
> > @@ -970,8 +1003,74 @@ static int bma400_write_event_config(struct iio_dev *indio_dev,
> > {
> > int ret;
> > struct bma400_data *data = iio_priv(indio_dev);
> > + int reg, msk, value, field_value;
> >
> > switch (chan->type) {
> > + case IIO_ACCEL:
> > + switch (dir) {
> > + case IIO_EV_DIR_RISING:
> > + reg = BMA400_GEN1INT_CONFIG0;
> > + msk = BMA400_INT_GEN1_MSK;
> > + value = 2;
> > + field_value = FIELD_PREP(BMA400_INT_GEN1_MSK, state);
>
> Hopefully you can use msk in here and the compiler can tell it's constant...
field_value = FIELD_PREP(msk, state);
is this the fix for error reported by kernel test robot?
>
> > + break;
> > + case IIO_EV_DIR_FALLING:
> > + reg = BMA400_GEN2INT_CONFIG0;
> > + msk = BMA400_INT_GEN2_MSK;
> > + value = 0;
> > + field_value = FIELD_PREP(BMA400_INT_GEN2_MSK, state);
> > + break;
> > + default:
> > + return -EINVAL;
> > + }
> > +
> > + mutex_lock(&data->mutex);
> > + /* Enabling all axis for interrupt evaluation */
> > + ret = regmap_write(data->regmap, reg, 0xF8);
> > + if (ret) {
> > + mutex_unlock(&data->mutex);
> > + return ret;
> > + }
> > +
> > + /* OR combination of all axis for interrupt evaluation */
> > + ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG1_OFF,
> > + value);
> > + if (ret) {
> > + mutex_unlock(&data->mutex);
> > + return ret;
> > + }
> > +
> > + /* Initial value to avoid interrupts while enabling*/
> > + ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
> > + 0x0A);
> > + if (ret) {
> > + mutex_unlock(&data->mutex);
> > + return ret;
> > + }
> > +
> > + /* Initial duration value to avoid interrupts while enabling*/
> > + ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG31_OFF,
> > + 0x0F);
> > + if (ret) {
> > + mutex_unlock(&data->mutex);
> > + return ret;
> > + }
> > +
> > + ret = regmap_update_bits(data->regmap, BMA400_INT1_MAP_REG,
> > + msk, field_value);
> > + if (ret) {
> > + mutex_unlock(&data->mutex);
> > + return ret;
> > + }
> > +
> > + ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG0_REG,
> > + msk, field_value);
> > + mutex_unlock(&data->mutex);
> > + if (ret)
> > + return ret;
>
> This whole stack or mutex_unlock() error handling is a good hint that you should
> just factor out this case as a separate function then you can use a goto to
> deal with the unlock cleanly.
Sure, I will fix the error handling in the proper way in the next patch.
>
> > +
> > + set_mask_bits(&data->generic_event_en, msk, field_value);
> > + return 0;
> > case IIO_STEPS:
> > mutex_lock(&data->mutex);
> > if (!data->steps_enabled) {
> > @@ -1028,6 +1127,118 @@ static int bma400_write_event_config(struct iio_dev *indio_dev,
> > }
> > }
> >
> > +static int get_gen_config_reg(enum iio_event_direction dir)
> > +{
> > + switch (dir) {
> > + case IIO_EV_DIR_FALLING:
> > + return BMA400_GEN2INT_CONFIG0;
> > + case IIO_EV_DIR_RISING:
> > + return BMA400_GEN1INT_CONFIG0;
> > + default:
> > + return -EINVAL;
> > + }
> > +}
> > +
> > +static int bma400_read_event_value(struct iio_dev *indio_dev,
> > + const struct iio_chan_spec *chan,
> > + enum iio_event_type type,
> > + enum iio_event_direction dir,
> > + enum iio_event_info info,
> > + int *val, int *val2)
> > +{
> > + struct bma400_data *data = iio_priv(indio_dev);
> > + int ret;
> > + u8 reg, duration[2];
> > +
> > + reg = get_gen_config_reg(dir);
> > + if (reg < 0)
> > + return -EINVAL;
> > +
> > + *val2 = 0;
> > + switch (info) {
> > + case IIO_EV_INFO_VALUE:
> > + mutex_lock(&data->mutex);
> > + ret = regmap_read(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
> > + val);
> > + mutex_unlock(&data->mutex);
> > + if (ret)
> > + return ret;
> > + return IIO_VAL_INT;
> > + case IIO_EV_INFO_PERIOD:
> > + mutex_lock(&data->mutex);
> > + ret = regmap_bulk_read(data->regmap,
> > + reg + BMA400_GEN_CONFIG3_OFF,
> > + duration, sizeof(duration));
> > + mutex_unlock(&data->mutex);
> > + if (ret)
> > + return ret;
> > + *val = get_unaligned_be16(duration);
>
> As well as dma safety question, you could just have used a __be16 for
> duration then you can use be16_to_cpu() as you know it is aligned.
For dma safety, do I need to allocate memory by using local kmalloc() or
I can use __be16 local variable for regmap_bulk_read()?
>
> > + return IIO_VAL_INT;
> > + case IIO_EV_INFO_HYSTERESIS:
> > + mutex_lock(&data->mutex);
> > + ret = regmap_read(data->regmap, reg, val);
> > + mutex_unlock(&data->mutex);
> > + if (ret)
> > + return ret;
> > + *val = FIELD_GET(BMA400_GEN_HYST_MSK, *val);
> > + return IIO_VAL_INT;
> > + default:
> > + return -EINVAL;
> > + }
> > +}
> > +
> > +static int bma400_write_event_value(struct iio_dev *indio_dev,
> > + const struct iio_chan_spec *chan,
> > + enum iio_event_type type,
> > + enum iio_event_direction dir,
> > + enum iio_event_info info,
> > + int val, int val2)
> > +{
> > + struct bma400_data *data = iio_priv(indio_dev);
> > + int ret;
> > + u8 reg, duration[2];
> > +
> > + reg = get_gen_config_reg(dir);
> > + if (reg < 0)
> > + return -EINVAL;
> > +
> > + switch (info) {
> > + case IIO_EV_INFO_VALUE:
> > + if (val < 1 || val > 255)
> > + return -EINVAL;
> > +
> > + mutex_lock(&data->mutex);
> > + ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
> > + val);
> > + mutex_unlock(&data->mutex);
> > + return ret;
> > + case IIO_EV_INFO_PERIOD:
> > + if (val < 1 || val > 65535)
> > + return -EINVAL;
> > +
> > + put_unaligned_be16(val, duration);
> > +
> > + mutex_lock(&data->mutex);
> > + ret = regmap_bulk_write(data->regmap,
> > + reg + BMA400_GEN_CONFIG3_OFF,
> > + duration, sizeof(duration));
>
> I can't remember if we are safe or not with bulk_writes but at least
> in theory we might not be and should be using a dma safe buffer.
Here also for regmap_bulk_write() can I allocate the memory locally by using
kmalloc().
>
> Also locking not necessary in various places in here.
I will fix the locking in all the patches in the next series.
>
> > + mutex_unlock(&data->mutex);
> > + return ret;
> > + case IIO_EV_INFO_HYSTERESIS:
> > + if (val < 0 || val > 3)
> > + return -EINVAL;
> > +
> > + mutex_lock(&data->mutex);
> > + ret = regmap_update_bits(data->regmap, reg,
> > + BMA400_GEN_HYST_MSK,
> > + FIELD_PREP(BMA400_GEN_HYST_MSK, val));
> > + mutex_unlock(&data->mutex);
> > + return ret;
> > + default:
> > + return -EINVAL;
> > + }
> > +}
> > +
>
Thank you,
Jagath
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 9/9] iio: accel: bma400: Add support for activity and inactivity events
2022-04-18 22:09 ` Jagath Jog J
@ 2022-04-24 15:40 ` Jonathan Cameron
2022-04-25 12:03 ` jagath jogj
0 siblings, 1 reply; 30+ messages in thread
From: Jonathan Cameron @ 2022-04-24 15:40 UTC (permalink / raw)
To: Jagath Jog J; +Cc: dan, andy.shevchenko, linux-iio, linux-kernel
On Tue, 19 Apr 2022 03:39:43 +0530
Jagath Jog J <jagathjog1996@gmail.com> wrote:
> Hello Jonathan,
>
> Thanks for your suggestions, I will fix the locking and unlocking for all
> patches in the next series.
>
> Please can you guide me for auto build test error reported by kernel test
> robot for set_mask_bits(&data->generic_event_en, msk, field_value);
> in this patch.
>
> On Sat, Apr 16, 2022 at 05:55:37PM +0100, Jonathan Cameron wrote:
> > On Tue, 12 Apr 2022 02:01:33 +0530
> > Jagath Jog J <jagathjog1996@gmail.com> wrote:
> >
> > > Add support for activity and inactivity events for all axis based on the
> > > threshold, duration and hysteresis value set from the userspace. INT1 pin
> > > is used to interrupt and event is pushed to userspace.
> > >
> > > Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
> > > ---
> > > drivers/iio/accel/bma400.h | 11 ++
> > > drivers/iio/accel/bma400_core.c | 229 ++++++++++++++++++++++++++++++++
> > > 2 files changed, 240 insertions(+)
> > >
> > > diff --git a/drivers/iio/accel/bma400.h b/drivers/iio/accel/bma400.h
> > > index bc4641279be3..cbf8035c817e 100644
> > > --- a/drivers/iio/accel/bma400.h
> > > +++ b/drivers/iio/accel/bma400.h
> > > @@ -93,6 +93,17 @@
> > > #define BMA400_ACC_ODR_MIN_WHOLE_HZ 25
> > > #define BMA400_ACC_ODR_MIN_HZ 12
> > >
> > > +/* Generic interrupts register */
> > > +#define BMA400_GEN1INT_CONFIG0 0x3f
> > > +#define BMA400_GEN2INT_CONFIG0 0x4A
> > > +#define BMA400_GEN_CONFIG1_OFF 0x01
> > > +#define BMA400_GEN_CONFIG2_OFF 0x02
> > > +#define BMA400_GEN_CONFIG3_OFF 0x03
> > > +#define BMA400_GEN_CONFIG31_OFF 0x04
> > > +#define BMA400_INT_GEN1_MSK BIT(2)
> > > +#define BMA400_INT_GEN2_MSK BIT(3)
> > > +#define BMA400_GEN_HYST_MSK GENMASK(1, 0)
> > > +
> > > /*
> > > * BMA400_SCALE_MIN macro value represents m/s^2 for 1 LSB before
> > > * converting to micro values for +-2g range.
> > > diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
> > > index b6c79cfabaa4..226a5f63d1a6 100644
> > > --- a/drivers/iio/accel/bma400_core.c
> > > +++ b/drivers/iio/accel/bma400_core.c
> > > @@ -79,6 +79,7 @@ struct bma400_data {
> > > int steps_enabled;
> > > bool step_event_en;
> > > bool activity_event_en;
> > > + u8 generic_event_en;
> > > /* Correct time stamp alignment */
> > > struct {
> > > __le16 buff[3];
> > > @@ -188,6 +189,25 @@ static const struct iio_event_spec bma400_activity_event = {
> > > .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE),
> > > };
> > >
> > > +static const struct iio_event_spec bma400_accel_event[] = {
> > > + {
> > > + .type = IIO_EV_TYPE_MAG,
> > > + .dir = IIO_EV_DIR_FALLING,
> > > + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
> > > + BIT(IIO_EV_INFO_PERIOD) |
> > > + BIT(IIO_EV_INFO_HYSTERESIS) |
> > > + BIT(IIO_EV_INFO_ENABLE),
> > > + },
> > > + {
> > > + .type = IIO_EV_TYPE_MAG,
> > > + .dir = IIO_EV_DIR_RISING,
> > > + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
> > > + BIT(IIO_EV_INFO_PERIOD) |
> > > + BIT(IIO_EV_INFO_HYSTERESIS) |
> > > + BIT(IIO_EV_INFO_ENABLE),
> > > + },
> > > +};
> > > +
> > > #define BMA400_ACC_CHANNEL(_index, _axis) { \
> > > .type = IIO_ACCEL, \
> > > .modified = 1, \
> > > @@ -207,6 +227,8 @@ static const struct iio_event_spec bma400_activity_event = {
> > > .storagebits = 16, \
> > > .endianness = IIO_LE, \
> > > }, \
> > > + .event_spec = bma400_accel_event, \
> > > + .num_event_specs = ARRAY_SIZE(bma400_accel_event) \
> > > }
> > >
> > > #define BMA400_ACTIVITY_CHANNEL(_chan2) { \
> > > @@ -954,6 +976,17 @@ static int bma400_read_event_config(struct iio_dev *indio_dev,
> > > struct bma400_data *data = iio_priv(indio_dev);
> > >
> > > switch (chan->type) {
> > > + case IIO_ACCEL:
> > > + switch (dir) {
> > > + case IIO_EV_DIR_RISING:
> > > + return FIELD_GET(BMA400_INT_GEN1_MSK,
> > > + data->generic_event_en);
> > > + case IIO_EV_DIR_FALLING:
> > > + return FIELD_GET(BMA400_INT_GEN2_MSK,
> > > + data->generic_event_en);
> > > + default:
> > > + return -EINVAL;
> > > + }
> > > case IIO_STEPS:
> > > return data->step_event_en;
> > > case IIO_ACTIVITY:
> > > @@ -970,8 +1003,74 @@ static int bma400_write_event_config(struct iio_dev *indio_dev,
> > > {
> > > int ret;
> > > struct bma400_data *data = iio_priv(indio_dev);
> > > + int reg, msk, value, field_value;
> > >
> > > switch (chan->type) {
> > > + case IIO_ACCEL:
> > > + switch (dir) {
> > > + case IIO_EV_DIR_RISING:
> > > + reg = BMA400_GEN1INT_CONFIG0;
> > > + msk = BMA400_INT_GEN1_MSK;
> > > + value = 2;
> > > + field_value = FIELD_PREP(BMA400_INT_GEN1_MSK, state);
> >
> > Hopefully you can use msk in here and the compiler can tell it's constant...
>
> field_value = FIELD_PREP(msk, state);
> is this the fix for error reported by kernel test robot?
No. That issue seems to be triggered by the size of parameters passed
to the underlying cmpxchg behind set_mask_bits.
Specifically riscv cmpxchg only support 32 or 64 bit inputs.
https://elixir.bootlin.com/linux/latest/source/arch/riscv/include/asm/cmpxchg.h#L302
Easiest fix is probably just to make generic_event_en 32 bits.
..
> > > +static int bma400_read_event_value(struct iio_dev *indio_dev,
> > > + const struct iio_chan_spec *chan,
> > > + enum iio_event_type type,
> > > + enum iio_event_direction dir,
> > > + enum iio_event_info info,
> > > + int *val, int *val2)
> > > +{
> > > + struct bma400_data *data = iio_priv(indio_dev);
> > > + int ret;
> > > + u8 reg, duration[2];
> > > +
> > > + reg = get_gen_config_reg(dir);
> > > + if (reg < 0)
> > > + return -EINVAL;
> > > +
> > > + *val2 = 0;
> > > + switch (info) {
> > > + case IIO_EV_INFO_VALUE:
> > > + mutex_lock(&data->mutex);
> > > + ret = regmap_read(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
> > > + val);
> > > + mutex_unlock(&data->mutex);
> > > + if (ret)
> > > + return ret;
> > > + return IIO_VAL_INT;
> > > + case IIO_EV_INFO_PERIOD:
> > > + mutex_lock(&data->mutex);
> > > + ret = regmap_bulk_read(data->regmap,
> > > + reg + BMA400_GEN_CONFIG3_OFF,
> > > + duration, sizeof(duration));
> > > + mutex_unlock(&data->mutex);
> > > + if (ret)
> > > + return ret;
> > > + *val = get_unaligned_be16(duration);
> >
> > As well as dma safety question, you could just have used a __be16 for
> > duration then you can use be16_to_cpu() as you know it is aligned.
>
> For dma safety, do I need to allocate memory by using local kmalloc() or
> I can use __be16 local variable for regmap_bulk_read()?
Ah. i've been unclear there. Was pointing out that if we didn't need
to force alignment larger for DMA safety then using __be16 would have
ensured that this was correctly aligned. However we do need to
force it so either use a kmalloc'd buffer as you suggest or
play games with an aligned buffer in the iio_priv() region.
Note however that we have a bug in IIO currently as we have
been forcing alignment to L1 cache size which is wrong (not enough in some cases
and far too much in others). I'll be posting
some patches to fix that in the next few days.
>
> >
> > > + return IIO_VAL_INT;
> > > + case IIO_EV_INFO_HYSTERESIS:
> > > + mutex_lock(&data->mutex);
> > > + ret = regmap_read(data->regmap, reg, val);
> > > + mutex_unlock(&data->mutex);
> > > + if (ret)
> > > + return ret;
> > > + *val = FIELD_GET(BMA400_GEN_HYST_MSK, *val);
> > > + return IIO_VAL_INT;
> > > + default:
> > > + return -EINVAL;
> > > + }
> > > +}
> > > +
> > > +static int bma400_write_event_value(struct iio_dev *indio_dev,
> > > + const struct iio_chan_spec *chan,
> > > + enum iio_event_type type,
> > > + enum iio_event_direction dir,
> > > + enum iio_event_info info,
> > > + int val, int val2)
> > > +{
> > > + struct bma400_data *data = iio_priv(indio_dev);
> > > + int ret;
> > > + u8 reg, duration[2];
> > > +
> > > + reg = get_gen_config_reg(dir);
> > > + if (reg < 0)
> > > + return -EINVAL;
> > > +
> > > + switch (info) {
> > > + case IIO_EV_INFO_VALUE:
> > > + if (val < 1 || val > 255)
> > > + return -EINVAL;
> > > +
> > > + mutex_lock(&data->mutex);
> > > + ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
> > > + val);
> > > + mutex_unlock(&data->mutex);
> > > + return ret;
> > > + case IIO_EV_INFO_PERIOD:
> > > + if (val < 1 || val > 65535)
> > > + return -EINVAL;
> > > +
> > > + put_unaligned_be16(val, duration);
> > > +
> > > + mutex_lock(&data->mutex);
> > > + ret = regmap_bulk_write(data->regmap,
> > > + reg + BMA400_GEN_CONFIG3_OFF,
> > > + duration, sizeof(duration));
> >
> > I can't remember if we are safe or not with bulk_writes but at least
> > in theory we might not be and should be using a dma safe buffer.
>
> Here also for regmap_bulk_write() can I allocate the memory locally by using
> kmalloc().
Yes though that's usually a pain to handle in comparison with a buffer in iio_priv()
as you have to free it again.
>
> >
> > Also locking not necessary in various places in here.
>
> I will fix the locking in all the patches in the next series.
>
> >
> > > + mutex_unlock(&data->mutex);
> > > + return ret;
> > > + case IIO_EV_INFO_HYSTERESIS:
> > > + if (val < 0 || val > 3)
> > > + return -EINVAL;
> > > +
> > > + mutex_lock(&data->mutex);
> > > + ret = regmap_update_bits(data->regmap, reg,
> > > + BMA400_GEN_HYST_MSK,
> > > + FIELD_PREP(BMA400_GEN_HYST_MSK, val));
> > > + mutex_unlock(&data->mutex);
> > > + return ret;
> > > + default:
> > > + return -EINVAL;
> > > + }
> > > +}
> > > +
> >
>
> Thank you,
> Jagath
Thanks,
Jonathan
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v3 9/9] iio: accel: bma400: Add support for activity and inactivity events
2022-04-24 15:40 ` Jonathan Cameron
@ 2022-04-25 12:03 ` jagath jogj
0 siblings, 0 replies; 30+ messages in thread
From: jagath jogj @ 2022-04-25 12:03 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Dan Robertson, Andy Shevchenko, linux-iio, Linux Kernel Mailing List
Hello Jonathan,
On Sun, Apr 24, 2022 at 9:02 PM Jonathan Cameron <jic23@kernel.org> wrote:
>
> On Tue, 19 Apr 2022 03:39:43 +0530
> Jagath Jog J <jagathjog1996@gmail.com> wrote:
>
> > Hello Jonathan,
> >
> > Thanks for your suggestions, I will fix the locking and unlocking for all
> > patches in the next series.
> >
> > Please can you guide me for auto build test error reported by kernel test
> > robot for set_mask_bits(&data->generic_event_en, msk, field_value);
> > in this patch.
> >
> > On Sat, Apr 16, 2022 at 05:55:37PM +0100, Jonathan Cameron wrote:
> > > On Tue, 12 Apr 2022 02:01:33 +0530
> > > Jagath Jog J <jagathjog1996@gmail.com> wrote:
> > >
> > > > Add support for activity and inactivity events for all axis based on the
> > > > threshold, duration and hysteresis value set from the userspace. INT1 pin
> > > > is used to interrupt and event is pushed to userspace.
> > > >
> > > > Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
> > > > ---
> > > > drivers/iio/accel/bma400.h | 11 ++
> > > > drivers/iio/accel/bma400_core.c | 229 ++++++++++++++++++++++++++++++++
> > > > 2 files changed, 240 insertions(+)
> > > >
> > > > diff --git a/drivers/iio/accel/bma400.h b/drivers/iio/accel/bma400.h
> > > > index bc4641279be3..cbf8035c817e 100644
> > > > --- a/drivers/iio/accel/bma400.h
> > > > +++ b/drivers/iio/accel/bma400.h
> > > > @@ -93,6 +93,17 @@
> > > > #define BMA400_ACC_ODR_MIN_WHOLE_HZ 25
> > > > #define BMA400_ACC_ODR_MIN_HZ 12
> > > >
> > > > +/* Generic interrupts register */
> > > > +#define BMA400_GEN1INT_CONFIG0 0x3f
> > > > +#define BMA400_GEN2INT_CONFIG0 0x4A
> > > > +#define BMA400_GEN_CONFIG1_OFF 0x01
> > > > +#define BMA400_GEN_CONFIG2_OFF 0x02
> > > > +#define BMA400_GEN_CONFIG3_OFF 0x03
> > > > +#define BMA400_GEN_CONFIG31_OFF 0x04
> > > > +#define BMA400_INT_GEN1_MSK BIT(2)
> > > > +#define BMA400_INT_GEN2_MSK BIT(3)
> > > > +#define BMA400_GEN_HYST_MSK GENMASK(1, 0)
> > > > +
> > > > /*
> > > > * BMA400_SCALE_MIN macro value represents m/s^2 for 1 LSB before
> > > > * converting to micro values for +-2g range.
> > > > diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
> > > > index b6c79cfabaa4..226a5f63d1a6 100644
> > > > --- a/drivers/iio/accel/bma400_core.c
> > > > +++ b/drivers/iio/accel/bma400_core.c
> > > > @@ -79,6 +79,7 @@ struct bma400_data {
> > > > int steps_enabled;
> > > > bool step_event_en;
> > > > bool activity_event_en;
> > > > + u8 generic_event_en;
> > > > /* Correct time stamp alignment */
> > > > struct {
> > > > __le16 buff[3];
> > > > @@ -188,6 +189,25 @@ static const struct iio_event_spec bma400_activity_event = {
> > > > .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE),
> > > > };
> > > >
> > > > +static const struct iio_event_spec bma400_accel_event[] = {
> > > > + {
> > > > + .type = IIO_EV_TYPE_MAG,
> > > > + .dir = IIO_EV_DIR_FALLING,
> > > > + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
> > > > + BIT(IIO_EV_INFO_PERIOD) |
> > > > + BIT(IIO_EV_INFO_HYSTERESIS) |
> > > > + BIT(IIO_EV_INFO_ENABLE),
> > > > + },
> > > > + {
> > > > + .type = IIO_EV_TYPE_MAG,
> > > > + .dir = IIO_EV_DIR_RISING,
> > > > + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
> > > > + BIT(IIO_EV_INFO_PERIOD) |
> > > > + BIT(IIO_EV_INFO_HYSTERESIS) |
> > > > + BIT(IIO_EV_INFO_ENABLE),
> > > > + },
> > > > +};
> > > > +
> > > > #define BMA400_ACC_CHANNEL(_index, _axis) { \
> > > > .type = IIO_ACCEL, \
> > > > .modified = 1, \
> > > > @@ -207,6 +227,8 @@ static const struct iio_event_spec bma400_activity_event = {
> > > > .storagebits = 16, \
> > > > .endianness = IIO_LE, \
> > > > }, \
> > > > + .event_spec = bma400_accel_event, \
> > > > + .num_event_specs = ARRAY_SIZE(bma400_accel_event) \
> > > > }
> > > >
> > > > #define BMA400_ACTIVITY_CHANNEL(_chan2) { \
> > > > @@ -954,6 +976,17 @@ static int bma400_read_event_config(struct iio_dev *indio_dev,
> > > > struct bma400_data *data = iio_priv(indio_dev);
> > > >
> > > > switch (chan->type) {
> > > > + case IIO_ACCEL:
> > > > + switch (dir) {
> > > > + case IIO_EV_DIR_RISING:
> > > > + return FIELD_GET(BMA400_INT_GEN1_MSK,
> > > > + data->generic_event_en);
> > > > + case IIO_EV_DIR_FALLING:
> > > > + return FIELD_GET(BMA400_INT_GEN2_MSK,
> > > > + data->generic_event_en);
> > > > + default:
> > > > + return -EINVAL;
> > > > + }
> > > > case IIO_STEPS:
> > > > return data->step_event_en;
> > > > case IIO_ACTIVITY:
> > > > @@ -970,8 +1003,74 @@ static int bma400_write_event_config(struct iio_dev *indio_dev,
> > > > {
> > > > int ret;
> > > > struct bma400_data *data = iio_priv(indio_dev);
> > > > + int reg, msk, value, field_value;
> > > >
> > > > switch (chan->type) {
> > > > + case IIO_ACCEL:
> > > > + switch (dir) {
> > > > + case IIO_EV_DIR_RISING:
> > > > + reg = BMA400_GEN1INT_CONFIG0;
> > > > + msk = BMA400_INT_GEN1_MSK;
> > > > + value = 2;
> > > > + field_value = FIELD_PREP(BMA400_INT_GEN1_MSK, state);
> > >
> > > Hopefully you can use msk in here and the compiler can tell it's constant...
> >
> > field_value = FIELD_PREP(msk, state);
> > is this the fix for error reported by kernel test robot?
> No. That issue seems to be triggered by the size of parameters passed
> to the underlying cmpxchg behind set_mask_bits.
> Specifically riscv cmpxchg only support 32 or 64 bit inputs.
> https://elixir.bootlin.com/linux/latest/source/arch/riscv/include/asm/cmpxchg.h#L302
>
> Easiest fix is probably just to make generic_event_en 32 bits.
In the patch series v4 I have declared generic_event_en as unsigned int.
> ..
>
> > > > +static int bma400_read_event_value(struct iio_dev *indio_dev,
> > > > + const struct iio_chan_spec *chan,
> > > > + enum iio_event_type type,
> > > > + enum iio_event_direction dir,
> > > > + enum iio_event_info info,
> > > > + int *val, int *val2)
> > > > +{
> > > > + struct bma400_data *data = iio_priv(indio_dev);
> > > > + int ret;
> > > > + u8 reg, duration[2];
> > > > +
> > > > + reg = get_gen_config_reg(dir);
> > > > + if (reg < 0)
> > > > + return -EINVAL;
> > > > +
> > > > + *val2 = 0;
> > > > + switch (info) {
> > > > + case IIO_EV_INFO_VALUE:
> > > > + mutex_lock(&data->mutex);
> > > > + ret = regmap_read(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
> > > > + val);
> > > > + mutex_unlock(&data->mutex);
> > > > + if (ret)
> > > > + return ret;
> > > > + return IIO_VAL_INT;
> > > > + case IIO_EV_INFO_PERIOD:
> > > > + mutex_lock(&data->mutex);
> > > > + ret = regmap_bulk_read(data->regmap,
> > > > + reg + BMA400_GEN_CONFIG3_OFF,
> > > > + duration, sizeof(duration));
> > > > + mutex_unlock(&data->mutex);
> > > > + if (ret)
> > > > + return ret;
> > > > + *val = get_unaligned_be16(duration);
> > >
> > > As well as dma safety question, you could just have used a __be16 for
> > > duration then you can use be16_to_cpu() as you know it is aligned.
> >
> > For dma safety, do I need to allocate memory by using local kmalloc() or
> > I can use __be16 local variable for regmap_bulk_read()?
>
> Ah. i've been unclear there. Was pointing out that if we didn't need
> to force alignment larger for DMA safety then using __be16 would have
> ensured that this was correctly aligned. However we do need to
> force it so either use a kmalloc'd buffer as you suggest or
> play games with an aligned buffer in the iio_priv() region.
In v4 series, I have used a __be16 buffer in the iio_priv() region for
duration so
that it can be used for both regmap_bulk_read() and regmap_bulk_write().
>
> Note however that we have a bug in IIO currently as we have
> been forcing alignment to L1 cache size which is wrong (not enough in some cases
> and far too much in others). I'll be posting
> some patches to fix that in the next few days.
>
>
> >
> > >
> > > > + return IIO_VAL_INT;
> > > > + case IIO_EV_INFO_HYSTERESIS:
> > > > + mutex_lock(&data->mutex);
> > > > + ret = regmap_read(data->regmap, reg, val);
> > > > + mutex_unlock(&data->mutex);
> > > > + if (ret)
> > > > + return ret;
> > > > + *val = FIELD_GET(BMA400_GEN_HYST_MSK, *val);
> > > > + return IIO_VAL_INT;
> > > > + default:
> > > > + return -EINVAL;
> > > > + }
> > > > +}
> > > > +
> > > > +static int bma400_write_event_value(struct iio_dev *indio_dev,
> > > > + const struct iio_chan_spec *chan,
> > > > + enum iio_event_type type,
> > > > + enum iio_event_direction dir,
> > > > + enum iio_event_info info,
> > > > + int val, int val2)
> > > > +{
> > > > + struct bma400_data *data = iio_priv(indio_dev);
> > > > + int ret;
> > > > + u8 reg, duration[2];
> > > > +
> > > > + reg = get_gen_config_reg(dir);
> > > > + if (reg < 0)
> > > > + return -EINVAL;
> > > > +
> > > > + switch (info) {
> > > > + case IIO_EV_INFO_VALUE:
> > > > + if (val < 1 || val > 255)
> > > > + return -EINVAL;
> > > > +
> > > > + mutex_lock(&data->mutex);
> > > > + ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG2_OFF,
> > > > + val);
> > > > + mutex_unlock(&data->mutex);
> > > > + return ret;
> > > > + case IIO_EV_INFO_PERIOD:
> > > > + if (val < 1 || val > 65535)
> > > > + return -EINVAL;
> > > > +
> > > > + put_unaligned_be16(val, duration);
> > > > +
> > > > + mutex_lock(&data->mutex);
> > > > + ret = regmap_bulk_write(data->regmap,
> > > > + reg + BMA400_GEN_CONFIG3_OFF,
> > > > + duration, sizeof(duration));
> > >
> > > I can't remember if we are safe or not with bulk_writes but at least
> > > in theory we might not be and should be using a dma safe buffer.
> >
> > Here also for regmap_bulk_write() can I allocate the memory locally by using
> > kmalloc().
>
> Yes though that's usually a pain to handle in comparison with a buffer in iio_priv()
> as you have to free it again.
>
> >
> > >
> > > Also locking not necessary in various places in here.
> >
> > I will fix the locking in all the patches in the next series.
> >
> > >
> > > > + mutex_unlock(&data->mutex);
> > > > + return ret;
> > > > + case IIO_EV_INFO_HYSTERESIS:
> > > > + if (val < 0 || val > 3)
> > > > + return -EINVAL;
> > > > +
> > > > + mutex_lock(&data->mutex);
> > > > + ret = regmap_update_bits(data->regmap, reg,
> > > > + BMA400_GEN_HYST_MSK,
> > > > + FIELD_PREP(BMA400_GEN_HYST_MSK, val));
> > > > + mutex_unlock(&data->mutex);
> > > > + return ret;
> > > > + default:
> > > > + return -EINVAL;
> > > > + }
> > > > +}
> > > > +
> > >
> >
> > Thank you,
> > Jagath
>
> Thanks,
>
> Jonathan
>
>
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2022-04-25 12:03 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-11 20:31 [PATCH v3 0/9] iio: accel: bma400: Add buffer, step and activity/inactivity Jagath Jog J
2022-04-11 20:31 ` [PATCH v3 1/9] iio: accel: bma400: Fix the scale min and max macro values Jagath Jog J
2022-04-12 8:59 ` Andy Shevchenko
2022-04-11 20:31 ` [PATCH v3 2/9] iio: accel: bma400: Reordering of header files Jagath Jog J
2022-04-12 9:00 ` Andy Shevchenko
2022-04-11 20:31 ` [PATCH v3 3/9] iio: accel: bma400: conversion to device-managed function Jagath Jog J
2022-04-12 9:04 ` Andy Shevchenko
2022-04-11 20:31 ` [PATCH v3 4/9] iio: accel: bma400: Add triggered buffer support Jagath Jog J
2022-04-12 9:12 ` Andy Shevchenko
2022-04-12 19:30 ` Jagath Jog J
[not found] ` <CAHp75Vc9MO2GxX81JQfzGRjM=nWLaQ-Uy9bV-dR1GMj1oQwjSQ@mail.gmail.com>
[not found] ` <CAHp75Vef21YmiKAvz-Kt-C=jb+mMCJeV_fwPAza9UwCuKy6omQ@mail.gmail.com>
2022-04-13 14:23 ` Jagath Jog J
2022-04-14 13:22 ` Jagath Jog J
2022-04-16 16:38 ` Jonathan Cameron
2022-04-11 20:31 ` [PATCH v3 5/9] iio: accel: bma400: Add separate channel for step counter Jagath Jog J
2022-04-16 16:41 ` Jonathan Cameron
2022-04-11 20:31 ` [PATCH v3 6/9] iio: accel: bma400: Add step change event Jagath Jog J
2022-04-11 20:31 ` [PATCH v3 7/9] iio: accel: bma400: Add activity recognition support Jagath Jog J
2022-04-16 16:47 ` Jonathan Cameron
2022-04-11 20:31 ` [PATCH v3 8/9] iio: accel: bma400: Add debugfs register access support Jagath Jog J
2022-04-16 16:48 ` Jonathan Cameron
2022-04-11 20:31 ` [PATCH v3 9/9] iio: accel: bma400: Add support for activity and inactivity events Jagath Jog J
2022-04-12 5:21 ` kernel test robot
2022-04-12 10:41 ` kernel test robot
2022-04-16 16:55 ` Jonathan Cameron
2022-04-18 22:09 ` Jagath Jog J
2022-04-24 15:40 ` Jonathan Cameron
2022-04-25 12:03 ` jagath jogj
2022-04-12 6:44 kernel test robot
2022-04-12 7:38 ` Dan Carpenter
2022-04-12 7:38 ` Dan Carpenter
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.