Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Gustavo Silva and committed by
Jonathan Cameron
7c62cd9c a4135386

+138
+138
drivers/iio/imu/bmi270/bmi270_core.c
··· 31 31 #define BMI270_INT_STATUS_1_REG 0x1d 32 32 #define BMI270_INT_STATUS_1_ACC_GYR_DRDY_MSK GENMASK(7, 6) 33 33 34 + #define BMI270_SC_OUT_0_REG 0x1e 35 + 34 36 #define BMI270_INTERNAL_STATUS_REG 0x21 35 37 #define BMI270_INTERNAL_STATUS_MSG_MSK GENMASK(3, 0) 36 38 #define BMI270_INTERNAL_STATUS_MSG_INIT_OK 0x01 ··· 40 38 #define BMI270_INTERNAL_STATUS_ODR_50HZ_ERR_MSK BIT(6) 41 39 42 40 #define BMI270_TEMPERATURE_0_REG 0x22 41 + 42 + #define BMI270_FEAT_PAGE_REG 0x2f 43 43 44 44 #define BMI270_ACC_CONF_REG 0x40 45 45 #define BMI270_ACC_CONF_ODR_MSK GENMASK(3, 0) ··· 94 90 #define BMI270_PWR_CTRL_ACCEL_EN_MSK BIT(2) 95 91 #define BMI270_PWR_CTRL_TEMP_EN_MSK BIT(3) 96 92 93 + #define BMI270_STEP_SC26_RST_CNT_MSK BIT(10) 94 + #define BMI270_STEP_SC26_EN_CNT_MSK BIT(12) 95 + 97 96 /* See datasheet section 4.6.14, Temperature Sensor */ 98 97 #define BMI270_TEMP_OFFSET 11776 99 98 #define BMI270_TEMP_SCALE 1953125 ··· 118 111 struct iio_trigger *trig; 119 112 /* Protect device's private data from concurrent access */ 120 113 struct mutex mutex; 114 + bool steps_enabled; 121 115 122 116 /* 123 117 * Where IIO_DMA_MINALIGN may be larger than 8 bytes, align to ··· 128 120 __le16 channels[6]; 129 121 aligned_s64 timestamp; 130 122 } buffer __aligned(IIO_DMA_MINALIGN); 123 + /* 124 + * Variable to access feature registers. It can be accessed concurrently 125 + * with the 'buffer' variable 126 + */ 127 + __le16 regval __aligned(IIO_DMA_MINALIGN); 131 128 }; 132 129 133 130 enum bmi270_scan { ··· 294 281 .num = ARRAY_SIZE(bmi270_gyro_odr), 295 282 }, 296 283 }; 284 + 285 + enum bmi270_feature_reg_id { 286 + BMI270_SC_26_REG, 287 + }; 288 + 289 + struct bmi270_feature_reg { 290 + u8 page; 291 + u8 addr; 292 + }; 293 + 294 + static const struct bmi270_feature_reg bmi270_feature_regs[] = { 295 + [BMI270_SC_26_REG] = { 296 + .page = 6, 297 + .addr = 0x32, 298 + }, 299 + }; 300 + 301 + static int bmi270_write_feature_reg(struct bmi270_data *data, 302 + enum bmi270_feature_reg_id id, 303 + u16 val) 304 + { 305 + const struct bmi270_feature_reg *reg = &bmi270_feature_regs[id]; 306 + int ret; 307 + 308 + ret = regmap_write(data->regmap, BMI270_FEAT_PAGE_REG, reg->page); 309 + if (ret) 310 + return ret; 311 + 312 + data->regval = cpu_to_le16(val); 313 + return regmap_bulk_write(data->regmap, reg->addr, &data->regval, 314 + sizeof(data->regval)); 315 + } 316 + 317 + static int bmi270_read_feature_reg(struct bmi270_data *data, 318 + enum bmi270_feature_reg_id id, 319 + u16 *val) 320 + { 321 + const struct bmi270_feature_reg *reg = &bmi270_feature_regs[id]; 322 + int ret; 323 + 324 + ret = regmap_write(data->regmap, BMI270_FEAT_PAGE_REG, reg->page); 325 + if (ret) 326 + return ret; 327 + 328 + ret = regmap_bulk_read(data->regmap, reg->addr, &data->regval, 329 + sizeof(data->regval)); 330 + if (ret) 331 + return ret; 332 + 333 + *val = le16_to_cpu(data->regval); 334 + return 0; 335 + } 336 + 337 + static int bmi270_update_feature_reg(struct bmi270_data *data, 338 + enum bmi270_feature_reg_id id, 339 + u16 mask, u16 val) 340 + { 341 + u16 regval; 342 + int ret; 343 + 344 + ret = bmi270_read_feature_reg(data, id, &regval); 345 + if (ret) 346 + return ret; 347 + 348 + regval = (regval & ~mask) | (val & mask); 349 + 350 + return bmi270_write_feature_reg(data, id, regval); 351 + } 352 + 353 + static int bmi270_enable_steps(struct bmi270_data *data, int val) 354 + { 355 + int ret; 356 + 357 + guard(mutex)(&data->mutex); 358 + if (data->steps_enabled) 359 + return 0; 360 + 361 + ret = bmi270_update_feature_reg(data, BMI270_SC_26_REG, 362 + BMI270_STEP_SC26_EN_CNT_MSK, 363 + FIELD_PREP(BMI270_STEP_SC26_EN_CNT_MSK, 364 + val ? 1 : 0)); 365 + if (ret) 366 + return ret; 367 + 368 + data->steps_enabled = true; 369 + return 0; 370 + } 371 + 372 + static int bmi270_read_steps(struct bmi270_data *data, int *val) 373 + { 374 + __le16 steps_count; 375 + int ret; 376 + 377 + ret = regmap_bulk_read(data->regmap, BMI270_SC_OUT_0_REG, &steps_count, 378 + sizeof(steps_count)); 379 + if (ret) 380 + return ret; 381 + 382 + *val = sign_extend32(le16_to_cpu(steps_count), 15); 383 + return IIO_VAL_INT; 384 + } 297 385 298 386 static int bmi270_set_scale(struct bmi270_data *data, int chan_type, int uscale) 299 387 { ··· 665 551 struct bmi270_data *data = iio_priv(indio_dev); 666 552 667 553 switch (mask) { 554 + case IIO_CHAN_INFO_PROCESSED: 555 + return bmi270_read_steps(data, val); 668 556 case IIO_CHAN_INFO_RAW: 669 557 if (!iio_device_claim_direct(indio_dev)) 670 558 return -EBUSY; ··· 687 571 case IIO_CHAN_INFO_SAMP_FREQ: 688 572 ret = bmi270_get_odr(data, chan->type, val, val2); 689 573 return ret ? ret : IIO_VAL_INT_PLUS_MICRO; 574 + case IIO_CHAN_INFO_ENABLE: 575 + *val = data->steps_enabled ? 1 : 0; 576 + return IIO_VAL_INT; 690 577 default: 691 578 return -EINVAL; 692 579 } ··· 715 596 ret = bmi270_set_odr(data, chan->type, val, val2); 716 597 iio_device_release_direct(indio_dev); 717 598 return ret; 599 + case IIO_CHAN_INFO_ENABLE: 600 + return bmi270_enable_steps(data, val); 601 + case IIO_CHAN_INFO_PROCESSED: { 602 + if (val || !data->steps_enabled) 603 + return -EINVAL; 604 + 605 + guard(mutex)(&data->mutex); 606 + /* Clear step counter value */ 607 + return bmi270_update_feature_reg(data, BMI270_SC_26_REG, 608 + BMI270_STEP_SC26_RST_CNT_MSK, 609 + FIELD_PREP(BMI270_STEP_SC26_RST_CNT_MSK, 610 + 1)); 611 + } 718 612 default: 719 613 return -EINVAL; 720 614 } ··· 828 696 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 829 697 BIT(IIO_CHAN_INFO_SCALE) | 830 698 BIT(IIO_CHAN_INFO_OFFSET), 699 + .scan_index = -1, /* No buffer support */ 700 + }, 701 + { 702 + .type = IIO_STEPS, 703 + .info_mask_separate = BIT(IIO_CHAN_INFO_ENABLE) | 704 + BIT(IIO_CHAN_INFO_PROCESSED), 831 705 .scan_index = -1, /* No buffer support */ 832 706 }, 833 707 IIO_CHAN_SOFT_TIMESTAMP(BMI270_SCAN_TIMESTAMP),