Skip to content

Commit c65ce2c

Browse files
ggrsjic23
authored andcommitted
iio: imu: bmi270: add channel for step counter
Add a channel for enabling/disabling the step counter, reading the number of steps and resetting the counter. Reviewed-by: Andy Shevchenko <andy@kernel.org> Signed-off-by: Gustavo Silva <gustavograzs@gmail.com> Link: https://patch.msgid.link/20250616-bmi270-events-v3-1-16e37588604f@gmail.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
1 parent 250b76f commit c65ce2c

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed

drivers/iio/imu/bmi270/bmi270_core.c

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#define BMI270_INT_STATUS_1_REG 0x1d
3232
#define BMI270_INT_STATUS_1_ACC_GYR_DRDY_MSK GENMASK(7, 6)
3333

34+
#define BMI270_SC_OUT_0_REG 0x1e
35+
3436
#define BMI270_INTERNAL_STATUS_REG 0x21
3537
#define BMI270_INTERNAL_STATUS_MSG_MSK GENMASK(3, 0)
3638
#define BMI270_INTERNAL_STATUS_MSG_INIT_OK 0x01
@@ -39,6 +41,8 @@
3941

4042
#define BMI270_TEMPERATURE_0_REG 0x22
4143

44+
#define BMI270_FEAT_PAGE_REG 0x2f
45+
4246
#define BMI270_ACC_CONF_REG 0x40
4347
#define BMI270_ACC_CONF_ODR_MSK GENMASK(3, 0)
4448
#define BMI270_ACC_CONF_ODR_100HZ 0x08
@@ -90,6 +94,9 @@
9094
#define BMI270_PWR_CTRL_ACCEL_EN_MSK BIT(2)
9195
#define BMI270_PWR_CTRL_TEMP_EN_MSK BIT(3)
9296

97+
#define BMI270_STEP_SC26_RST_CNT_MSK BIT(10)
98+
#define BMI270_STEP_SC26_EN_CNT_MSK BIT(12)
99+
93100
/* See datasheet section 4.6.14, Temperature Sensor */
94101
#define BMI270_TEMP_OFFSET 11776
95102
#define BMI270_TEMP_SCALE 1953125
@@ -111,6 +118,7 @@ struct bmi270_data {
111118
struct iio_trigger *trig;
112119
/* Protect device's private data from concurrent access */
113120
struct mutex mutex;
121+
bool steps_enabled;
114122

115123
/*
116124
* Where IIO_DMA_MINALIGN may be larger than 8 bytes, align to
@@ -120,6 +128,11 @@ struct bmi270_data {
120128
__le16 channels[6];
121129
aligned_s64 timestamp;
122130
} buffer __aligned(IIO_DMA_MINALIGN);
131+
/*
132+
* Variable to access feature registers. It can be accessed concurrently
133+
* with the 'buffer' variable
134+
*/
135+
__le16 regval __aligned(IIO_DMA_MINALIGN);
123136
};
124137

125138
enum bmi270_scan {
@@ -282,6 +295,107 @@ static const struct bmi270_odr_item bmi270_odr_table[] = {
282295
},
283296
};
284297

298+
enum bmi270_feature_reg_id {
299+
BMI270_SC_26_REG,
300+
};
301+
302+
struct bmi270_feature_reg {
303+
u8 page;
304+
u8 addr;
305+
};
306+
307+
static const struct bmi270_feature_reg bmi270_feature_regs[] = {
308+
[BMI270_SC_26_REG] = {
309+
.page = 6,
310+
.addr = 0x32,
311+
},
312+
};
313+
314+
static int bmi270_write_feature_reg(struct bmi270_data *data,
315+
enum bmi270_feature_reg_id id,
316+
u16 val)
317+
{
318+
const struct bmi270_feature_reg *reg = &bmi270_feature_regs[id];
319+
int ret;
320+
321+
ret = regmap_write(data->regmap, BMI270_FEAT_PAGE_REG, reg->page);
322+
if (ret)
323+
return ret;
324+
325+
data->regval = cpu_to_le16(val);
326+
return regmap_bulk_write(data->regmap, reg->addr, &data->regval,
327+
sizeof(data->regval));
328+
}
329+
330+
static int bmi270_read_feature_reg(struct bmi270_data *data,
331+
enum bmi270_feature_reg_id id,
332+
u16 *val)
333+
{
334+
const struct bmi270_feature_reg *reg = &bmi270_feature_regs[id];
335+
int ret;
336+
337+
ret = regmap_write(data->regmap, BMI270_FEAT_PAGE_REG, reg->page);
338+
if (ret)
339+
return ret;
340+
341+
ret = regmap_bulk_read(data->regmap, reg->addr, &data->regval,
342+
sizeof(data->regval));
343+
if (ret)
344+
return ret;
345+
346+
*val = le16_to_cpu(data->regval);
347+
return 0;
348+
}
349+
350+
static int bmi270_update_feature_reg(struct bmi270_data *data,
351+
enum bmi270_feature_reg_id id,
352+
u16 mask, u16 val)
353+
{
354+
u16 regval;
355+
int ret;
356+
357+
ret = bmi270_read_feature_reg(data, id, &regval);
358+
if (ret)
359+
return ret;
360+
361+
regval = (regval & ~mask) | (val & mask);
362+
363+
return bmi270_write_feature_reg(data, id, regval);
364+
}
365+
366+
static int bmi270_enable_steps(struct bmi270_data *data, int val)
367+
{
368+
int ret;
369+
370+
guard(mutex)(&data->mutex);
371+
if (data->steps_enabled)
372+
return 0;
373+
374+
ret = bmi270_update_feature_reg(data, BMI270_SC_26_REG,
375+
BMI270_STEP_SC26_EN_CNT_MSK,
376+
FIELD_PREP(BMI270_STEP_SC26_EN_CNT_MSK,
377+
val ? 1 : 0));
378+
if (ret)
379+
return ret;
380+
381+
data->steps_enabled = true;
382+
return 0;
383+
}
384+
385+
static int bmi270_read_steps(struct bmi270_data *data, int *val)
386+
{
387+
__le16 steps_count;
388+
int ret;
389+
390+
ret = regmap_bulk_read(data->regmap, BMI270_SC_OUT_0_REG, &steps_count,
391+
sizeof(steps_count));
392+
if (ret)
393+
return ret;
394+
395+
*val = sign_extend32(le16_to_cpu(steps_count), 15);
396+
return IIO_VAL_INT;
397+
}
398+
285399
static int bmi270_set_scale(struct bmi270_data *data, int chan_type, int uscale)
286400
{
287401
int i;
@@ -551,6 +665,8 @@ static int bmi270_read_raw(struct iio_dev *indio_dev,
551665
struct bmi270_data *data = iio_priv(indio_dev);
552666

553667
switch (mask) {
668+
case IIO_CHAN_INFO_PROCESSED:
669+
return bmi270_read_steps(data, val);
554670
case IIO_CHAN_INFO_RAW:
555671
if (!iio_device_claim_direct(indio_dev))
556672
return -EBUSY;
@@ -571,6 +687,9 @@ static int bmi270_read_raw(struct iio_dev *indio_dev,
571687
case IIO_CHAN_INFO_SAMP_FREQ:
572688
ret = bmi270_get_odr(data, chan->type, val, val2);
573689
return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
690+
case IIO_CHAN_INFO_ENABLE:
691+
*val = data->steps_enabled ? 1 : 0;
692+
return IIO_VAL_INT;
574693
default:
575694
return -EINVAL;
576695
}
@@ -596,6 +715,19 @@ static int bmi270_write_raw(struct iio_dev *indio_dev,
596715
ret = bmi270_set_odr(data, chan->type, val, val2);
597716
iio_device_release_direct(indio_dev);
598717
return ret;
718+
case IIO_CHAN_INFO_ENABLE:
719+
return bmi270_enable_steps(data, val);
720+
case IIO_CHAN_INFO_PROCESSED: {
721+
if (val || !data->steps_enabled)
722+
return -EINVAL;
723+
724+
guard(mutex)(&data->mutex);
725+
/* Clear step counter value */
726+
return bmi270_update_feature_reg(data, BMI270_SC_26_REG,
727+
BMI270_STEP_SC26_RST_CNT_MSK,
728+
FIELD_PREP(BMI270_STEP_SC26_RST_CNT_MSK,
729+
1));
730+
}
599731
default:
600732
return -EINVAL;
601733
}
@@ -698,6 +830,12 @@ static const struct iio_chan_spec bmi270_channels[] = {
698830
BIT(IIO_CHAN_INFO_OFFSET),
699831
.scan_index = -1, /* No buffer support */
700832
},
833+
{
834+
.type = IIO_STEPS,
835+
.info_mask_separate = BIT(IIO_CHAN_INFO_ENABLE) |
836+
BIT(IIO_CHAN_INFO_PROCESSED),
837+
.scan_index = -1, /* No buffer support */
838+
},
701839
IIO_CHAN_SOFT_TIMESTAMP(BMI270_SCAN_TIMESTAMP),
702840
};
703841

0 commit comments

Comments
 (0)