[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <fe32537d44cbb187e1518740f33e3a6716dd363a.camel@gmail.com>
Date: Fri, 19 Sep 2025 13:05:19 +0100
From: Nuno Sá <noname.nuno@...il.com>
To: Akshay Jindal <akshayaj.lkd@...il.com>, dan@...obertson.com,
jic23@...nel.org, dlechner@...libre.com, nuno.sa@...log.com, andy@...nel.org
Cc: shuah@...nel.org, linux-iio@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH] iio: accel: bma400: Refactor generic interrupt
configuration
Hi,
Thanks for your patch.
On Fri, 2025-09-19 at 00:37 +0530, Akshay Jindal wrote:
> Refactor the generic interrupt configuration logic to improve readability
> and reduce repetitive code. Replace hard-coded register values with macros
> and enums, making it clearer what configuration is written to hardware.
>
> Introduce a const struct to map event direction to the corresponding
> generic interrupt. This removes the need for switch statements in multiple
> callbacks, including activity event setup, read_event_value, and
> write_event_value, while still performing the selection at runtime.
>
> This change has no functional impact but simplifies the code and makes it
> easier to maintain and extend in future updates.
>
> Signed-off-by: Akshay Jindal <akshayaj.lkd@...il.com>
> ---
You may be trying to refactor too much in one single patch. I would maybe think
about splitting this into 2/3 logical changes.
> drivers/iio/accel/bma400.h | 71 +++++++++++++++---
> drivers/iio/accel/bma400_core.c | 128 ++++++++++++++++----------------
> 2 files changed, 125 insertions(+), 74 deletions(-)
>
> diff --git a/drivers/iio/accel/bma400.h b/drivers/iio/accel/bma400.h
> index 932358b45f17..ab7d1d139b66 100644
> --- a/drivers/iio/accel/bma400.h
> +++ b/drivers/iio/accel/bma400.h
> @@ -68,7 +68,19 @@
> #define BMA400_CMD_REG 0x7e
>
> /* Interrupt registers */
> -#define BMA400_INT_CONFIG0_REG 0x1f
> +#define BMA400_INT_CONFIG0_REG 0x1f
> +#define BMA400_INT_CONFIG0_ORTN_CHG_MASK BIT(1)
> +#define BMA400_INT_CONFIG0_GEN1_MASK BIT(2)
> +#define BMA400_INT_CONFIG0_GEN2_MASK BIT(3)
> +#define BMA400_INT_CONFIG0_FIFO_FULL_MASK BIT(5)
> +#define BMA400_INT_CONFIG0_FIFO_WTRMRK_MASK BIT(6)
> +#define BMA400_INT_CONFIG0_DRDY_MASK BIT(7)
> +
> +enum generic_intr {
> + GEN1_INTR,
> + GEN2_INTR
> +};
> +
> #define BMA400_INT_CONFIG1_REG 0x20
> #define BMA400_INT1_MAP_REG 0x21
> #define BMA400_INT_IO_CTRL_REG 0x24
> @@ -96,15 +108,53 @@
> #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)
> +#define BMA400_GENINT_CONFIG_REG_BASE 0x3f
> +#define BMA400_NUM_GENINT_CONFIG_REGS 11
> +#define BMA400_GENINT_CONFIG_REG(gen_intr, config_idx) \
> + (BMA400_GENINT_CONFIG_REG_BASE + \
> + (gen_intr) * BMA400_NUM_GENINT_CONFIG_REGS + \
> + (config_idx))
Not sure the above macro helps that much. More on this below...
> +
> +/* Generic Interrupt Config0 register */
> +#define BMA400_GENINT_CONFIG0_HYST_MASK GENMASK(1, 0)
> +#define BMA400_GENINT_CONFIG0_REF_UPD_MODE_MASK GENMASK(3, 2)
> +#define BMA400_GENINT_CONFIG0_DATA_SRC_MASK BIT(4)
> +#define BMA400_GENINT_CONFIG0_X_EN_MASK BIT(5)
> +#define BMA400_GENINT_CONFIG0_Y_EN_MASK BIT(6)
> +#define BMA400_GENINT_CONFIG0_Z_EN_MASK BIT(7)
> +
> +enum bma400_hysteresis_config {
> + NO_HYSTERESIS,
> + HYSTERESIS_24MG,
> + HYSTERESIS_48MG,
> + HYSTERESIS_96MG
> +};
> +
> +enum bma400_accel_data_src {
> + ACCEL_FILT1,
> + ACCEL_FILT2
> +};
> +
> +enum bma400_ref_updt_mode {
> + BMA400_REF_MANUAL_UPDT_MODE,
> + BMA400_REF_ONETIME_UPDT_MODE,
> + BMA400_REF_EVERYTIME_UPDT_MODE,
> + BMA400_REF_EVERYTIME_LP_UPDT_MODE
> +};
> +
> +/* Generic Interrupt Config1 register */
> +#define BMA400_GENINT_CONFIG1_AXES_COMB_MASK BIT(0)
> +#define BMA400_GENINT_CONFIG1_DETCT_CRIT_MASK BIT(1)
> +
> +enum bma400_genintr_acceleval_axescomb {
> + BMA400_EVAL_X_OR_Y_OR_Z,
> + BMA400_EVAL_X_AND_Y_AND_Z,
> +};
> +
> +enum bma400_detect_criterion {
> + BMA400_DETECT_INACTIVITY,
> + BMA400_DETECT_ACTIVITY,
> +};
>
> /* TAP config registers */
> #define BMA400_TAP_CONFIG 0x57
> @@ -119,6 +169,7 @@
> #define BMA400_TAP_QUIETDT_MSK GENMASK(5, 4)
> #define BMA400_TAP_TIM_LIST_LEN 4
>
> +
> /*
> * 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 85e23badf733..d59c26b8a57f 100644
> --- a/drivers/iio/accel/bma400_core.c
> +++ b/drivers/iio/accel/bma400_core.c
> @@ -121,6 +121,29 @@ struct bma400_data {
> __be16 duration;
> };
>
> +struct bma400_genintr_info {
> + u8 genintr;
> + unsigned int intrmask;
> + enum iio_event_direction dir;
> + enum bma400_detect_criterion detect_mode;
> +};
> +
> +/* Lookup struct for determining GEN1/GEN2 based on dir */
> +static const struct bma400_genintr_info bma400_genintrs[] = {
> + [IIO_EV_DIR_RISING] = {
> + .genintr = GEN1_INTR, /* 0 for GEN1 */
> + .intrmask = BMA400_INT_CONFIG0_GEN1_MASK,
> + .dir = IIO_EV_DIR_RISING,
> + .detect_mode = BMA400_DETECT_ACTIVITY,
> + },
> + [IIO_EV_DIR_FALLING] = {
> + .genintr = GEN2_INTR, /* 1 for GEN2 */
> + .intrmask = BMA400_INT_CONFIG0_GEN2_MASK,
> + .dir = IIO_EV_DIR_FALLING,
> + .detect_mode = BMA400_DETECT_INACTIVITY,
> + }
> +};
> +
> static bool bma400_is_writable_reg(struct device *dev, unsigned int reg)
> {
> switch (reg) {
> @@ -1114,10 +1137,10 @@ static int bma400_read_event_config(struct iio_dev
> *indio_dev,
> case IIO_ACCEL:
> switch (dir) {
> case IIO_EV_DIR_RISING:
> - return FIELD_GET(BMA400_INT_GEN1_MSK,
> + return FIELD_GET(BMA400_INT_CONFIG0_GEN1_MASK,
> data->generic_event_en);
Like the above is above renaming defines in a more logical name. Not going to
opinate whether this name is better or not but you could put that (and other
similar changes) in one patch.
> case IIO_EV_DIR_FALLING:
> - return FIELD_GET(BMA400_INT_GEN2_MSK,
> + return FIELD_GET(BMA400_INT_CONFIG0_GEN2_MASK,
> data->generic_event_en);
> case IIO_EV_DIR_SINGLETAP:
> return FIELD_GET(BMA400_S_TAP_MSK,
> @@ -1159,59 +1182,50 @@ static int bma400_activity_event_en(struct bma400_data
> *data,
> enum iio_event_direction dir,
> int state)
> {
> - int ret, reg, msk, value;
> - int field_value = 0;
> -
> - switch (dir) {
> - case IIO_EV_DIR_RISING:
> - reg = BMA400_GEN1INT_CONFIG0;
> - msk = BMA400_INT_GEN1_MSK;
> - value = 2;
> - set_mask_bits(&field_value, BMA400_INT_GEN1_MSK,
> - FIELD_PREP(BMA400_INT_GEN1_MSK, state));
> - break;
> - case IIO_EV_DIR_FALLING:
> - reg = BMA400_GEN2INT_CONFIG0;
> - msk = BMA400_INT_GEN2_MSK;
> - value = 0;
> - set_mask_bits(&field_value, BMA400_INT_GEN2_MSK,
> - FIELD_PREP(BMA400_INT_GEN2_MSK, state));
> - break;
> - default:
> - return -EINVAL;
> - }
> + int ret, regval;
> + u8 genintr = bma400_genintrs[dir].genintr;
> + u8 detect_criterion = bma400_genintrs[dir].detect_mode;
> + unsigned int intrmask = bma400_genintrs[dir].intrmask;
>
Hmm, you should still have the switch case. Again, not sure the const struct
adds that much but I'm also fine with it. But I would do:
switch (dir) {
case IIO_EV_DIR_RISING:
case IIO_EV_DIR_FALLING:
genintr = bma400_genintrs[dir].genintr;
detect_criterion = bma400_genintrs[dir].detect_mode;
intrmask = bma400_genintrs[dir].intrmask;
default:
return -EINVAL;
> /* Enabling all axis for interrupt evaluation */
> - ret = regmap_write(data->regmap, reg, 0xF8);
> + ret = regmap_write(data->regmap, BMA400_GENINT_CONFIG_REG(genintr,
> 0),
> + BMA400_GENINT_CONFIG0_X_EN_MASK |
> + BMA400_GENINT_CONFIG0_Y_EN_MASK |
> + BMA400_GENINT_CONFIG0_Z_EN_MASK|
> + BMA400_REF_EVERYTIME_UPDT_MODE);
> if (ret)
> return ret;
>
> /* OR combination of all axis for interrupt evaluation */
> - ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG1_OFF,
> value);
> + regval = FIELD_PREP(BMA400_GENINT_CONFIG1_AXES_COMB_MASK,
> BMA400_EVAL_X_OR_Y_OR_Z) |
> + FIELD_PREP(BMA400_GENINT_CONFIG1_DETCT_CRIT_MASK,
> detect_criterion);
> + ret = regmap_write(data->regmap, BMA400_GENINT_CONFIG_REG(genintr,
> 1), regval);
> if (ret)
> return ret;
>
> /* Initial value to avoid interrupts while enabling*/
> - ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG2_OFF, 0x0A);
> + ret = regmap_write(data->regmap, BMA400_GENINT_CONFIG_REG(genintr,
> 2), 0x0A);
I do not think readability is improved here. The former is way easier to read
IMO. Also, we still have the magic 0x0A.
> if (ret)
> return ret;
>
> /* Initial duration value to avoid interrupts while enabling*/
> - ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG31_OFF,
> 0x0F);
> + ret = regmap_write(data->regmap, BMA400_GENINT_CONFIG_REG(genintr,
> 4), 0x0F);
> if (ret)
> return ret;
>
> - ret = regmap_update_bits(data->regmap, BMA400_INT1_MAP_REG, msk,
> - field_value);
> + regval = FIELD_PREP(BMA400_INT_CONFIG0_GEN1_MASK, state);
> + if (genintr)
> + regval = FIELD_PREP(BMA400_INT_CONFIG0_GEN2_MASK, state);
> +
> + ret = regmap_update_bits(data->regmap, BMA400_INT1_MAP_REG, intrmask,
> regval);
> if (ret)
> return ret;
>
> - ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG0_REG, msk,
> - field_value);
> + ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG0_REG,
> intrmask, regval);
> if (ret)
> return ret;
>
> - set_mask_bits(&data->generic_event_en, msk, field_value);
> + set_mask_bits(&data->generic_event_en, intrmask, regval);
> return 0;
> }
>
> @@ -1336,18 +1350,6 @@ 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,
> @@ -1356,22 +1358,20 @@ static int bma400_read_event_value(struct iio_dev
> *indio_dev,
> int *val, int *val2)
> {
> struct bma400_data *data = iio_priv(indio_dev);
> - int ret, reg, reg_val, raw;
> + int ret, genintr, reg_val, raw;
>
> if (chan->type != IIO_ACCEL)
> return -EINVAL;
>
> switch (type) {
> case IIO_EV_TYPE_MAG:
> - reg = get_gen_config_reg(dir);
> - if (reg < 0)
> - return -EINVAL;
> + genintr = bma400_genintrs[dir].genintr;
Again you should make sure dir is valid. You could keep get_gen_config_reg() and
do something similar with what I suggested above.
>
> *val2 = 0;
> switch (info) {
> case IIO_EV_INFO_VALUE:
> ret = regmap_read(data->regmap,
> - reg + BMA400_GEN_CONFIG2_OFF,
> + BMA400_GENINT_CONFIG_REG(genintr,
> 2),
> val);
> if (ret)
> return ret;
> @@ -1379,7 +1379,7 @@ static int bma400_read_event_value(struct iio_dev
> *indio_dev,
> case IIO_EV_INFO_PERIOD:
> mutex_lock(&data->mutex);
> ret = regmap_bulk_read(data->regmap,
> - reg + BMA400_GEN_CONFIG3_OFF,
> +
> BMA400_GENINT_CONFIG_REG(genintr, 3),
> &data->duration,
> sizeof(data->duration));
> if (ret) {
> @@ -1390,10 +1390,12 @@ static int bma400_read_event_value(struct iio_dev
> *indio_dev,
> mutex_unlock(&data->mutex);
> return IIO_VAL_INT;
> case IIO_EV_INFO_HYSTERESIS:
> - ret = regmap_read(data->regmap, reg, val);
> + ret = regmap_read(data->regmap,
> + BMA400_GENINT_CONFIG_REG(genintr,
> 0),
> + val);
One more case where I don't really think this macro is doing readability any
better.
- Nuno Sá
Powered by blists - more mailing lists