From: Antoniu Miclaus Date: Sat, 21 Mar 2026 10:04:56 +0000 (+0200) Subject: iio: accel: adxl372: introduce chip_info structure X-Git-Tag: v7.1-rc1~17^2~120^2~73 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=23d742859a2dd20b1e96ab0828fa26227c47f328;p=thirdparty%2Fkernel%2Fstable.git iio: accel: adxl372: introduce chip_info structure Introduce a chip_info structure to parameterize device-specific properties such as ODR/bandwidth frequency tables, activity/inactivity timer scale factors, and the maximum ODR value. This refactors the driver to use chip_info lookups instead of hardcoded values, preparing the driver to support multiple device variants. The sampling_frequency and filter_low_pass_3db_frequency available attributes are switched from custom sysfs callbacks to read_avail() based handling via info_mask_shared_by_type_available. This enforces consistent formatting through the IIO framework and makes the values accessible to in-kernel consumers. The SPI/I2C probe functions are updated to pass a chip_info pointer instead of a device name string. No functional change intended. Signed-off-by: Antoniu Miclaus Signed-off-by: Jonathan Cameron --- diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c index 6763f8ed9f7f1..1592b25ecb2c8 100644 --- a/drivers/iio/accel/adxl372.c +++ b/drivers/iio/accel/adxl372.c @@ -181,6 +181,7 @@ enum adxl372_odr { ADXL372_ODR_1600HZ, ADXL372_ODR_3200HZ, ADXL372_ODR_6400HZ, + ADXL372_ODR_NUM }; enum adxl372_bandwidth { @@ -215,14 +216,35 @@ enum adxl372_fifo_mode { ADXL372_FIFO_OLD_SAVED }; -static const int adxl372_samp_freq_tbl[5] = { - 400, 800, 1600, 3200, 6400, +static const int adxl372_samp_freq_tbl[ADXL372_ODR_NUM] = { + [ADXL372_ODR_400HZ] = 400, + [ADXL372_ODR_800HZ] = 800, + [ADXL372_ODR_1600HZ] = 1600, + [ADXL372_ODR_3200HZ] = 3200, + [ADXL372_ODR_6400HZ] = 6400, }; -static const int adxl372_bw_freq_tbl[5] = { - 200, 400, 800, 1600, 3200, +static const int adxl372_bw_freq_tbl[ADXL372_ODR_NUM] = { + [ADXL372_BW_200HZ] = 200, + [ADXL372_BW_400HZ] = 400, + [ADXL372_BW_800HZ] = 800, + [ADXL372_BW_1600HZ] = 1600, + [ADXL372_BW_3200HZ] = 3200, }; +const struct adxl372_chip_info adxl372_chip_info = { + .name = "adxl372", + .samp_freq_tbl = adxl372_samp_freq_tbl, + .bw_freq_tbl = adxl372_bw_freq_tbl, + .num_freqs = ARRAY_SIZE(adxl372_samp_freq_tbl), + .act_time_scale_us = 3300, + .act_time_scale_low_us = 6600, + .inact_time_scale_ms = 13, + .inact_time_scale_low_ms = 26, + .max_odr = ADXL372_ODR_6400HZ, +}; +EXPORT_SYMBOL_NS_GPL(adxl372_chip_info, "IIO_ADXL372"); + struct adxl372_axis_lookup { unsigned int bits; enum adxl372_fifo_format fifo_format; @@ -258,8 +280,12 @@ static const struct iio_event_spec adxl372_events[] = { .modified = 1, \ .channel2 = IIO_MOD_##axis, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ - BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ + .info_mask_shared_by_type = \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ + .info_mask_shared_by_type_available = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ .scan_index = index, \ .scan_type = { \ @@ -280,6 +306,7 @@ static const struct iio_chan_spec adxl372_channels[] = { }; struct adxl372_state { + const struct adxl372_chip_info *chip_info; int irq; struct device *dev; struct regmap *regmap; @@ -468,13 +495,14 @@ static int adxl372_set_activity_time_ms(struct adxl372_state *st, int ret; /* - * 3.3 ms per code is the scale factor of the TIME_ACT register for - * ODR = 6400 Hz. It is 6.6 ms per code for ODR = 3200 Hz and below. + * The scale factor of the TIME_ACT register depends on the ODR. + * A higher scale factor is used at the maximum ODR and a lower + * one at all other rates. */ - if (st->odr == ADXL372_ODR_6400HZ) - scale_factor = 3300; + if (st->odr == st->chip_info->max_odr) + scale_factor = st->chip_info->act_time_scale_us; else - scale_factor = 6600; + scale_factor = st->chip_info->act_time_scale_low_us; reg_val = DIV_ROUND_CLOSEST(act_time_ms * 1000, scale_factor); @@ -498,13 +526,14 @@ static int adxl372_set_inactivity_time_ms(struct adxl372_state *st, int ret; /* - * 13 ms per code is the scale factor of the TIME_INACT register for - * ODR = 6400 Hz. It is 26 ms per code for ODR = 3200 Hz and below. + * The scale factor of the TIME_INACT register depends on the ODR. + * A higher scale factor is used at the maximum ODR and a lower + * one at all other rates. */ - if (st->odr == ADXL372_ODR_6400HZ) - scale_factor = 13; + if (st->odr == st->chip_info->max_odr) + scale_factor = st->chip_info->inact_time_scale_ms; else - scale_factor = 26; + scale_factor = st->chip_info->inact_time_scale_low_ms; res = DIV_ROUND_CLOSEST(inact_time_ms, scale_factor); reg_val_h = (res >> 8) & 0xFF; @@ -714,7 +743,7 @@ static int adxl372_setup(struct adxl372_state *st) if (ret < 0) return ret; - ret = adxl372_set_odr(st, ADXL372_ODR_6400HZ); + ret = adxl372_set_odr(st, st->chip_info->max_odr); if (ret < 0) return ret; @@ -774,10 +803,10 @@ static int adxl372_read_raw(struct iio_dev *indio_dev, *val2 = ADXL372_USCALE; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_SAMP_FREQ: - *val = adxl372_samp_freq_tbl[st->odr]; + *val = st->chip_info->samp_freq_tbl[st->odr]; return IIO_VAL_INT; case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: - *val = adxl372_bw_freq_tbl[st->bw]; + *val = st->chip_info->bw_freq_tbl[st->bw]; return IIO_VAL_INT; } @@ -793,23 +822,17 @@ static int adxl372_write_raw(struct iio_dev *indio_dev, switch (info) { case IIO_CHAN_INFO_SAMP_FREQ: - odr_index = adxl372_find_closest_match(adxl372_samp_freq_tbl, - ARRAY_SIZE(adxl372_samp_freq_tbl), - val); + odr_index = adxl372_find_closest_match(st->chip_info->samp_freq_tbl, + st->chip_info->num_freqs, + val); ret = adxl372_set_odr(st, odr_index); if (ret < 0) return ret; - /* - * The timer period depends on the ODR selected. - * At 3200 Hz and below, it is 6.6 ms; at 6400 Hz, it is 3.3 ms - */ + /* Recalculate activity time as the timer period depends on ODR */ ret = adxl372_set_activity_time_ms(st, st->act_time_ms); if (ret < 0) return ret; - /* - * The timer period depends on the ODR selected. - * At 3200 Hz and below, it is 26 ms; at 6400 Hz, it is 13 ms - */ + /* Recalculate inactivity time as the timer period depends on ODR */ ret = adxl372_set_inactivity_time_ms(st, st->inact_time_ms); if (ret < 0) return ret; @@ -822,9 +845,9 @@ static int adxl372_write_raw(struct iio_dev *indio_dev, return ret; case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: - bw_index = adxl372_find_closest_match(adxl372_bw_freq_tbl, - ARRAY_SIZE(adxl372_bw_freq_tbl), - val); + bw_index = adxl372_find_closest_match(st->chip_info->bw_freq_tbl, + st->chip_info->num_freqs, + val); return adxl372_set_bandwidth(st, bw_index); default: return -EINVAL; @@ -954,24 +977,6 @@ static int adxl372_write_event_config(struct iio_dev *indio_dev, const struct ii return adxl372_set_interrupts(st, st->int1_bitmask, 0); } -static ssize_t adxl372_show_filter_freq_avail(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct adxl372_state *st = iio_priv(indio_dev); - int i; - size_t len = 0; - - for (i = 0; i <= st->odr; i++) - len += scnprintf(buf + len, PAGE_SIZE - len, - "%d ", adxl372_bw_freq_tbl[i]); - - buf[len - 1] = '\n'; - - return len; -} - static ssize_t adxl372_get_fifo_enabled(struct device *dev, struct device_attribute *attr, char *buf) @@ -1139,25 +1144,38 @@ static const struct iio_trigger_ops adxl372_peak_data_trigger_ops = { .set_trigger_state = adxl372_peak_dready_trig_set_state, }; -static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400"); -static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available, - 0444, adxl372_show_filter_freq_avail, NULL, 0); - -static struct attribute *adxl372_attributes[] = { - &iio_const_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr, - NULL, -}; +static int adxl372_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + struct adxl372_state *st = iio_priv(indio_dev); -static const struct attribute_group adxl372_attrs_group = { - .attrs = adxl372_attributes, -}; + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + *vals = st->chip_info->samp_freq_tbl; + *type = IIO_VAL_INT; + *length = st->chip_info->num_freqs; + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + *vals = st->chip_info->bw_freq_tbl; + *type = IIO_VAL_INT; + /* + * Bandwidth cannot exceed half the sampling frequency + * (Nyquist), so limit available values based on current ODR. + */ + *length = st->odr + 1; + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} static const struct iio_info adxl372_info = { .validate_trigger = &adxl372_validate_trigger, - .attrs = &adxl372_attrs_group, .read_raw = adxl372_read_raw, .write_raw = adxl372_write_raw, + .read_avail = adxl372_read_avail, .read_event_config = adxl372_read_event_config, .write_event_config = adxl372_write_event_config, .read_event_value = adxl372_read_event_value, @@ -1173,7 +1191,7 @@ bool adxl372_readable_noinc_reg(struct device *dev, unsigned int reg) EXPORT_SYMBOL_NS_GPL(adxl372_readable_noinc_reg, "IIO_ADXL372"); int adxl372_probe(struct device *dev, struct regmap *regmap, - int irq, const char *name) + int irq, const struct adxl372_chip_info *chip_info) { struct iio_dev *indio_dev; struct adxl372_state *st; @@ -1189,13 +1207,14 @@ int adxl372_probe(struct device *dev, struct regmap *regmap, st->dev = dev; st->regmap = regmap; st->irq = irq; + st->chip_info = chip_info; mutex_init(&st->threshold_m); indio_dev->channels = adxl372_channels; indio_dev->num_channels = ARRAY_SIZE(adxl372_channels); indio_dev->available_scan_masks = adxl372_channel_masks; - indio_dev->name = name; + indio_dev->name = chip_info->name; indio_dev->info = &adxl372_info; indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; diff --git a/drivers/iio/accel/adxl372.h b/drivers/iio/accel/adxl372.h index 80a0aa9714fc0..3ce06609446cf 100644 --- a/drivers/iio/accel/adxl372.h +++ b/drivers/iio/accel/adxl372.h @@ -10,8 +10,22 @@ #define ADXL372_REVID 0x03 +struct adxl372_chip_info { + const char *name; + const int *samp_freq_tbl; + const int *bw_freq_tbl; + unsigned int num_freqs; + unsigned int act_time_scale_us; + unsigned int act_time_scale_low_us; + unsigned int inact_time_scale_ms; + unsigned int inact_time_scale_low_ms; + unsigned int max_odr; +}; + +extern const struct adxl372_chip_info adxl372_chip_info; + int adxl372_probe(struct device *dev, struct regmap *regmap, - int irq, const char *name); + int irq, const struct adxl372_chip_info *chip_info); bool adxl372_readable_noinc_reg(struct device *dev, unsigned int reg); #endif /* _ADXL372_H_ */ diff --git a/drivers/iio/accel/adxl372_i2c.c b/drivers/iio/accel/adxl372_i2c.c index 186d4fe9a556a..5d135b1150c8c 100644 --- a/drivers/iio/accel/adxl372_i2c.c +++ b/drivers/iio/accel/adxl372_i2c.c @@ -20,11 +20,13 @@ static const struct regmap_config adxl372_regmap_config = { static int adxl372_i2c_probe(struct i2c_client *client) { - const struct i2c_device_id *id = i2c_client_get_device_id(client); + const struct adxl372_chip_info *chip_info; struct regmap *regmap; unsigned int regval; int ret; + chip_info = i2c_get_match_data(client); + regmap = devm_regmap_init_i2c(client, &adxl372_regmap_config); if (IS_ERR(regmap)) return PTR_ERR(regmap); @@ -38,17 +40,17 @@ static int adxl372_i2c_probe(struct i2c_client *client) dev_warn(&client->dev, "I2C might not work properly with other devices on the bus"); - return adxl372_probe(&client->dev, regmap, client->irq, id->name); + return adxl372_probe(&client->dev, regmap, client->irq, chip_info); } static const struct i2c_device_id adxl372_i2c_id[] = { - { "adxl372" }, + { "adxl372", (kernel_ulong_t)&adxl372_chip_info }, { } }; MODULE_DEVICE_TABLE(i2c, adxl372_i2c_id); static const struct of_device_id adxl372_of_match[] = { - { .compatible = "adi,adxl372" }, + { .compatible = "adi,adxl372", .data = &adxl372_chip_info }, { } }; MODULE_DEVICE_TABLE(of, adxl372_of_match); diff --git a/drivers/iio/accel/adxl372_spi.c b/drivers/iio/accel/adxl372_spi.c index 39941b519c3bb..e96a355bfe675 100644 --- a/drivers/iio/accel/adxl372_spi.c +++ b/drivers/iio/accel/adxl372_spi.c @@ -22,24 +22,26 @@ static const struct regmap_config adxl372_spi_regmap_config = { static int adxl372_spi_probe(struct spi_device *spi) { - const struct spi_device_id *id = spi_get_device_id(spi); + const struct adxl372_chip_info *chip_info; struct regmap *regmap; + chip_info = spi_get_device_match_data(spi); + regmap = devm_regmap_init_spi(spi, &adxl372_spi_regmap_config); if (IS_ERR(regmap)) return PTR_ERR(regmap); - return adxl372_probe(&spi->dev, regmap, spi->irq, id->name); + return adxl372_probe(&spi->dev, regmap, spi->irq, chip_info); } static const struct spi_device_id adxl372_spi_id[] = { - { "adxl372", 0 }, + { "adxl372", (kernel_ulong_t)&adxl372_chip_info }, { } }; MODULE_DEVICE_TABLE(spi, adxl372_spi_id); static const struct of_device_id adxl372_of_match[] = { - { .compatible = "adi,adxl372" }, + { .compatible = "adi,adxl372", .data = &adxl372_chip_info }, { } }; MODULE_DEVICE_TABLE(of, adxl372_of_match);