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 step counter watermark event

Add support for generating events when the step counter reaches the
configurable watermark.

Reviewed-by: Andy Shevchenko <andy@kernel.org>
Signed-off-by: Gustavo Silva <gustavograzs@gmail.com>
Link: https://patch.msgid.link/20250616-bmi270-events-v3-2-16e37588604f@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Gustavo Silva and committed by
Jonathan Cameron
e602ee39 7c62cd9c

+166 -3
+166 -3
drivers/iio/imu/bmi270/bmi270_core.c
··· 8 8 #include <linux/regmap.h> 9 9 #include <linux/units.h> 10 10 11 + #include <linux/iio/events.h> 11 12 #include <linux/iio/iio.h> 12 13 #include <linux/iio/sysfs.h> 13 14 #include <linux/iio/trigger.h> ··· 28 27 29 28 #define BMI270_ACCEL_X_REG 0x0c 30 29 #define BMI270_ANG_VEL_X_REG 0x12 30 + 31 + #define BMI270_INT_STATUS_0_REG 0x1c 32 + #define BMI270_INT_STATUS_0_STEP_CNT_MSK BIT(1) 31 33 32 34 #define BMI270_INT_STATUS_1_REG 0x1d 33 35 #define BMI270_INT_STATUS_1_ACC_GYR_DRDY_MSK GENMASK(7, 6) ··· 78 74 #define BMI270_INT_LATCH_REG 0x55 79 75 #define BMI270_INT_LATCH_REG_MSK BIT(0) 80 76 77 + #define BMI270_INT1_MAP_FEAT_REG 0x56 78 + #define BMI270_INT2_MAP_FEAT_REG 0x57 79 + #define BMI270_INT_MAP_FEAT_STEP_CNT_WTRMRK_MSK BIT(1) 80 + 81 81 #define BMI270_INT_MAP_DATA_REG 0x58 82 82 #define BMI270_INT_MAP_DATA_DRDY_INT1_MSK BIT(2) 83 83 #define BMI270_INT_MAP_DATA_DRDY_INT2_MSK BIT(6) ··· 102 94 #define BMI270_PWR_CTRL_ACCEL_EN_MSK BIT(2) 103 95 #define BMI270_PWR_CTRL_TEMP_EN_MSK BIT(3) 104 96 97 + #define BMI270_STEP_SC26_WTRMRK_MSK GENMASK(9, 0) 105 98 #define BMI270_STEP_SC26_RST_CNT_MSK BIT(10) 106 99 #define BMI270_STEP_SC26_EN_CNT_MSK BIT(12) 107 100 108 101 /* See datasheet section 4.6.14, Temperature Sensor */ 109 102 #define BMI270_TEMP_OFFSET 11776 110 103 #define BMI270_TEMP_SCALE 1953125 104 + 105 + /* See page 90 of datasheet. The step counter "holds implicitly a 20x factor" */ 106 + #define BMI270_STEP_COUNTER_FACTOR 20 107 + #define BMI270_STEP_COUNTER_MAX 20460 111 108 112 109 #define BMI260_INIT_DATA_FILE "bmi260-init-data.fw" 113 110 #define BMI270_INIT_DATA_FILE "bmi270-init-data.fw" ··· 409 396 return IIO_VAL_INT; 410 397 } 411 398 399 + static int bmi270_int_map_reg(enum bmi270_irq_pin pin) 400 + { 401 + switch (pin) { 402 + case BMI270_IRQ_INT1: 403 + return BMI270_INT1_MAP_FEAT_REG; 404 + case BMI270_IRQ_INT2: 405 + return BMI270_INT2_MAP_FEAT_REG; 406 + default: 407 + return -EINVAL; 408 + } 409 + } 410 + 411 + static int bmi270_step_wtrmrk_en(struct bmi270_data *data, bool state) 412 + { 413 + int reg; 414 + 415 + guard(mutex)(&data->mutex); 416 + if (!data->steps_enabled) 417 + return -EINVAL; 418 + 419 + reg = bmi270_int_map_reg(data->irq_pin); 420 + if (reg < 0) 421 + return reg; 422 + 423 + return regmap_update_bits(data->regmap, reg, 424 + BMI270_INT_MAP_FEAT_STEP_CNT_WTRMRK_MSK, 425 + FIELD_PREP(BMI270_INT_MAP_FEAT_STEP_CNT_WTRMRK_MSK, 426 + state)); 427 + } 428 + 412 429 static int bmi270_set_scale(struct bmi270_data *data, int chan_type, int uscale) 413 430 { 414 431 int i; ··· 595 552 { 596 553 struct iio_dev *indio_dev = private; 597 554 struct bmi270_data *data = iio_priv(indio_dev); 598 - unsigned int status; 555 + unsigned int status0, status1; 556 + s64 timestamp = iio_get_time_ns(indio_dev); 599 557 int ret; 600 558 601 559 scoped_guard(mutex, &data->mutex) { 560 + ret = regmap_read(data->regmap, BMI270_INT_STATUS_0_REG, 561 + &status0); 562 + if (ret) 563 + return IRQ_NONE; 564 + 602 565 ret = regmap_read(data->regmap, BMI270_INT_STATUS_1_REG, 603 - &status); 566 + &status1); 604 567 if (ret) 605 568 return IRQ_NONE; 606 569 } 607 570 608 - if (FIELD_GET(BMI270_INT_STATUS_1_ACC_GYR_DRDY_MSK, status)) 571 + if (FIELD_GET(BMI270_INT_STATUS_1_ACC_GYR_DRDY_MSK, status1)) 609 572 iio_trigger_poll_nested(data->trig); 573 + 574 + if (FIELD_GET(BMI270_INT_STATUS_0_STEP_CNT_MSK, status0)) 575 + iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_STEPS, 0, 576 + IIO_EV_TYPE_CHANGE, 577 + IIO_EV_DIR_NONE), 578 + timestamp); 610 579 611 580 return IRQ_HANDLED; 612 581 } ··· 827 772 } 828 773 } 829 774 775 + static int bmi270_write_event_config(struct iio_dev *indio_dev, 776 + const struct iio_chan_spec *chan, 777 + enum iio_event_type type, 778 + enum iio_event_direction dir, bool state) 779 + { 780 + struct bmi270_data *data = iio_priv(indio_dev); 781 + 782 + switch (type) { 783 + case IIO_EV_TYPE_CHANGE: 784 + return bmi270_step_wtrmrk_en(data, state); 785 + default: 786 + return -EINVAL; 787 + } 788 + } 789 + 790 + static int bmi270_read_event_config(struct iio_dev *indio_dev, 791 + const struct iio_chan_spec *chan, 792 + enum iio_event_type type, 793 + enum iio_event_direction dir) 794 + { 795 + struct bmi270_data *data = iio_priv(indio_dev); 796 + int ret, reg, regval; 797 + 798 + guard(mutex)(&data->mutex); 799 + 800 + switch (chan->type) { 801 + case IIO_STEPS: 802 + reg = bmi270_int_map_reg(data->irq_pin); 803 + if (reg) 804 + return reg; 805 + 806 + ret = regmap_read(data->regmap, reg, &regval); 807 + if (ret) 808 + return ret; 809 + return FIELD_GET(BMI270_INT_MAP_FEAT_STEP_CNT_WTRMRK_MSK, 810 + regval) ? 1 : 0; 811 + default: 812 + return -EINVAL; 813 + } 814 + } 815 + 816 + static int bmi270_write_event_value(struct iio_dev *indio_dev, 817 + const struct iio_chan_spec *chan, 818 + enum iio_event_type type, 819 + enum iio_event_direction dir, 820 + enum iio_event_info info, 821 + int val, int val2) 822 + { 823 + struct bmi270_data *data = iio_priv(indio_dev); 824 + unsigned int raw; 825 + 826 + guard(mutex)(&data->mutex); 827 + 828 + switch (type) { 829 + case IIO_EV_TYPE_CHANGE: 830 + if (!in_range(val, 0, BMI270_STEP_COUNTER_MAX + 1)) 831 + return -EINVAL; 832 + 833 + raw = val / BMI270_STEP_COUNTER_FACTOR; 834 + return bmi270_update_feature_reg(data, BMI270_SC_26_REG, 835 + BMI270_STEP_SC26_WTRMRK_MSK, 836 + FIELD_PREP(BMI270_STEP_SC26_WTRMRK_MSK, 837 + raw)); 838 + default: 839 + return -EINVAL; 840 + } 841 + } 842 + 843 + static int bmi270_read_event_value(struct iio_dev *indio_dev, 844 + const struct iio_chan_spec *chan, 845 + enum iio_event_type type, 846 + enum iio_event_direction dir, 847 + enum iio_event_info info, 848 + int *val, int *val2) 849 + { 850 + struct bmi270_data *data = iio_priv(indio_dev); 851 + unsigned int raw; 852 + u16 regval; 853 + int ret; 854 + 855 + guard(mutex)(&data->mutex); 856 + 857 + switch (type) { 858 + case IIO_EV_TYPE_CHANGE: 859 + ret = bmi270_read_feature_reg(data, BMI270_SC_26_REG, &regval); 860 + if (ret) 861 + return ret; 862 + 863 + raw = FIELD_GET(BMI270_STEP_SC26_WTRMRK_MSK, regval); 864 + *val = raw * BMI270_STEP_COUNTER_FACTOR; 865 + return IIO_VAL_INT; 866 + default: 867 + return -EINVAL; 868 + } 869 + } 870 + 871 + static const struct iio_event_spec bmi270_step_wtrmrk_event = { 872 + .type = IIO_EV_TYPE_CHANGE, 873 + .dir = IIO_EV_DIR_NONE, 874 + .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) | BIT(IIO_EV_INFO_VALUE), 875 + }; 876 + 830 877 static const struct iio_info bmi270_info = { 831 878 .read_raw = bmi270_read_raw, 832 879 .write_raw = bmi270_write_raw, 833 880 .read_avail = bmi270_read_avail, 881 + .write_event_config = bmi270_write_event_config, 882 + .read_event_config = bmi270_read_event_config, 883 + .write_event_value = bmi270_write_event_value, 884 + .read_event_value = bmi270_read_event_value, 834 885 }; 835 886 836 887 #define BMI270_ACCEL_CHANNEL(_axis) { \ ··· 996 835 .info_mask_separate = BIT(IIO_CHAN_INFO_ENABLE) | 997 836 BIT(IIO_CHAN_INFO_PROCESSED), 998 837 .scan_index = -1, /* No buffer support */ 838 + .event_spec = &bmi270_step_wtrmrk_event, 839 + .num_event_specs = 1, 999 840 }, 1000 841 IIO_CHAN_SOFT_TIMESTAMP(BMI270_SCAN_TIMESTAMP), 1001 842 };