mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 16:44:58 +02:00
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>
This commit is contained in:
parent
a4135386fa
commit
7c62cd9c79
|
|
@ -31,6 +31,8 @@
|
|||
#define BMI270_INT_STATUS_1_REG 0x1d
|
||||
#define BMI270_INT_STATUS_1_ACC_GYR_DRDY_MSK GENMASK(7, 6)
|
||||
|
||||
#define BMI270_SC_OUT_0_REG 0x1e
|
||||
|
||||
#define BMI270_INTERNAL_STATUS_REG 0x21
|
||||
#define BMI270_INTERNAL_STATUS_MSG_MSK GENMASK(3, 0)
|
||||
#define BMI270_INTERNAL_STATUS_MSG_INIT_OK 0x01
|
||||
|
|
@ -39,6 +41,8 @@
|
|||
|
||||
#define BMI270_TEMPERATURE_0_REG 0x22
|
||||
|
||||
#define BMI270_FEAT_PAGE_REG 0x2f
|
||||
|
||||
#define BMI270_ACC_CONF_REG 0x40
|
||||
#define BMI270_ACC_CONF_ODR_MSK GENMASK(3, 0)
|
||||
#define BMI270_ACC_CONF_ODR_100HZ 0x08
|
||||
|
|
@ -90,6 +94,9 @@
|
|||
#define BMI270_PWR_CTRL_ACCEL_EN_MSK BIT(2)
|
||||
#define BMI270_PWR_CTRL_TEMP_EN_MSK BIT(3)
|
||||
|
||||
#define BMI270_STEP_SC26_RST_CNT_MSK BIT(10)
|
||||
#define BMI270_STEP_SC26_EN_CNT_MSK BIT(12)
|
||||
|
||||
/* See datasheet section 4.6.14, Temperature Sensor */
|
||||
#define BMI270_TEMP_OFFSET 11776
|
||||
#define BMI270_TEMP_SCALE 1953125
|
||||
|
|
@ -111,6 +118,7 @@ struct bmi270_data {
|
|||
struct iio_trigger *trig;
|
||||
/* Protect device's private data from concurrent access */
|
||||
struct mutex mutex;
|
||||
bool steps_enabled;
|
||||
|
||||
/*
|
||||
* Where IIO_DMA_MINALIGN may be larger than 8 bytes, align to
|
||||
|
|
@ -120,6 +128,11 @@ struct bmi270_data {
|
|||
__le16 channels[6];
|
||||
aligned_s64 timestamp;
|
||||
} buffer __aligned(IIO_DMA_MINALIGN);
|
||||
/*
|
||||
* Variable to access feature registers. It can be accessed concurrently
|
||||
* with the 'buffer' variable
|
||||
*/
|
||||
__le16 regval __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
enum bmi270_scan {
|
||||
|
|
@ -282,6 +295,107 @@ static const struct bmi270_odr_item bmi270_odr_table[] = {
|
|||
},
|
||||
};
|
||||
|
||||
enum bmi270_feature_reg_id {
|
||||
BMI270_SC_26_REG,
|
||||
};
|
||||
|
||||
struct bmi270_feature_reg {
|
||||
u8 page;
|
||||
u8 addr;
|
||||
};
|
||||
|
||||
static const struct bmi270_feature_reg bmi270_feature_regs[] = {
|
||||
[BMI270_SC_26_REG] = {
|
||||
.page = 6,
|
||||
.addr = 0x32,
|
||||
},
|
||||
};
|
||||
|
||||
static int bmi270_write_feature_reg(struct bmi270_data *data,
|
||||
enum bmi270_feature_reg_id id,
|
||||
u16 val)
|
||||
{
|
||||
const struct bmi270_feature_reg *reg = &bmi270_feature_regs[id];
|
||||
int ret;
|
||||
|
||||
ret = regmap_write(data->regmap, BMI270_FEAT_PAGE_REG, reg->page);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
data->regval = cpu_to_le16(val);
|
||||
return regmap_bulk_write(data->regmap, reg->addr, &data->regval,
|
||||
sizeof(data->regval));
|
||||
}
|
||||
|
||||
static int bmi270_read_feature_reg(struct bmi270_data *data,
|
||||
enum bmi270_feature_reg_id id,
|
||||
u16 *val)
|
||||
{
|
||||
const struct bmi270_feature_reg *reg = &bmi270_feature_regs[id];
|
||||
int ret;
|
||||
|
||||
ret = regmap_write(data->regmap, BMI270_FEAT_PAGE_REG, reg->page);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, reg->addr, &data->regval,
|
||||
sizeof(data->regval));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = le16_to_cpu(data->regval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bmi270_update_feature_reg(struct bmi270_data *data,
|
||||
enum bmi270_feature_reg_id id,
|
||||
u16 mask, u16 val)
|
||||
{
|
||||
u16 regval;
|
||||
int ret;
|
||||
|
||||
ret = bmi270_read_feature_reg(data, id, ®val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
regval = (regval & ~mask) | (val & mask);
|
||||
|
||||
return bmi270_write_feature_reg(data, id, regval);
|
||||
}
|
||||
|
||||
static int bmi270_enable_steps(struct bmi270_data *data, int val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
guard(mutex)(&data->mutex);
|
||||
if (data->steps_enabled)
|
||||
return 0;
|
||||
|
||||
ret = bmi270_update_feature_reg(data, BMI270_SC_26_REG,
|
||||
BMI270_STEP_SC26_EN_CNT_MSK,
|
||||
FIELD_PREP(BMI270_STEP_SC26_EN_CNT_MSK,
|
||||
val ? 1 : 0));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
data->steps_enabled = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bmi270_read_steps(struct bmi270_data *data, int *val)
|
||||
{
|
||||
__le16 steps_count;
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BMI270_SC_OUT_0_REG, &steps_count,
|
||||
sizeof(steps_count));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = sign_extend32(le16_to_cpu(steps_count), 15);
|
||||
return IIO_VAL_INT;
|
||||
}
|
||||
|
||||
static int bmi270_set_scale(struct bmi270_data *data, int chan_type, int uscale)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -551,6 +665,8 @@ static int bmi270_read_raw(struct iio_dev *indio_dev,
|
|||
struct bmi270_data *data = iio_priv(indio_dev);
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_PROCESSED:
|
||||
return bmi270_read_steps(data, val);
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
if (!iio_device_claim_direct(indio_dev))
|
||||
return -EBUSY;
|
||||
|
|
@ -571,6 +687,9 @@ static int bmi270_read_raw(struct iio_dev *indio_dev,
|
|||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
ret = bmi270_get_odr(data, chan->type, val, val2);
|
||||
return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
|
||||
case IIO_CHAN_INFO_ENABLE:
|
||||
*val = data->steps_enabled ? 1 : 0;
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -596,6 +715,19 @@ static int bmi270_write_raw(struct iio_dev *indio_dev,
|
|||
ret = bmi270_set_odr(data, chan->type, val, val2);
|
||||
iio_device_release_direct(indio_dev);
|
||||
return ret;
|
||||
case IIO_CHAN_INFO_ENABLE:
|
||||
return bmi270_enable_steps(data, val);
|
||||
case IIO_CHAN_INFO_PROCESSED: {
|
||||
if (val || !data->steps_enabled)
|
||||
return -EINVAL;
|
||||
|
||||
guard(mutex)(&data->mutex);
|
||||
/* Clear step counter value */
|
||||
return bmi270_update_feature_reg(data, BMI270_SC_26_REG,
|
||||
BMI270_STEP_SC26_RST_CNT_MSK,
|
||||
FIELD_PREP(BMI270_STEP_SC26_RST_CNT_MSK,
|
||||
1));
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -698,6 +830,12 @@ static const struct iio_chan_spec bmi270_channels[] = {
|
|||
BIT(IIO_CHAN_INFO_OFFSET),
|
||||
.scan_index = -1, /* No buffer support */
|
||||
},
|
||||
{
|
||||
.type = IIO_STEPS,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_ENABLE) |
|
||||
BIT(IIO_CHAN_INFO_PROCESSED),
|
||||
.scan_index = -1, /* No buffer support */
|
||||
},
|
||||
IIO_CHAN_SOFT_TIMESTAMP(BMI270_SCAN_TIMESTAMP),
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user