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: 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 <antoniu.miclaus@analog.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Antoniu Miclaus and committed by
Jonathan Cameron
23d74285 8c7440c6

+112 -75
+85 -66
drivers/iio/accel/adxl372.c
··· 181 181 ADXL372_ODR_1600HZ, 182 182 ADXL372_ODR_3200HZ, 183 183 ADXL372_ODR_6400HZ, 184 + ADXL372_ODR_NUM 184 185 }; 185 186 186 187 enum adxl372_bandwidth { ··· 216 215 ADXL372_FIFO_OLD_SAVED 217 216 }; 218 217 219 - static const int adxl372_samp_freq_tbl[5] = { 220 - 400, 800, 1600, 3200, 6400, 218 + static const int adxl372_samp_freq_tbl[ADXL372_ODR_NUM] = { 219 + [ADXL372_ODR_400HZ] = 400, 220 + [ADXL372_ODR_800HZ] = 800, 221 + [ADXL372_ODR_1600HZ] = 1600, 222 + [ADXL372_ODR_3200HZ] = 3200, 223 + [ADXL372_ODR_6400HZ] = 6400, 221 224 }; 222 225 223 - static const int adxl372_bw_freq_tbl[5] = { 224 - 200, 400, 800, 1600, 3200, 226 + static const int adxl372_bw_freq_tbl[ADXL372_ODR_NUM] = { 227 + [ADXL372_BW_200HZ] = 200, 228 + [ADXL372_BW_400HZ] = 400, 229 + [ADXL372_BW_800HZ] = 800, 230 + [ADXL372_BW_1600HZ] = 1600, 231 + [ADXL372_BW_3200HZ] = 3200, 225 232 }; 233 + 234 + const struct adxl372_chip_info adxl372_chip_info = { 235 + .name = "adxl372", 236 + .samp_freq_tbl = adxl372_samp_freq_tbl, 237 + .bw_freq_tbl = adxl372_bw_freq_tbl, 238 + .num_freqs = ARRAY_SIZE(adxl372_samp_freq_tbl), 239 + .act_time_scale_us = 3300, 240 + .act_time_scale_low_us = 6600, 241 + .inact_time_scale_ms = 13, 242 + .inact_time_scale_low_ms = 26, 243 + .max_odr = ADXL372_ODR_6400HZ, 244 + }; 245 + EXPORT_SYMBOL_NS_GPL(adxl372_chip_info, "IIO_ADXL372"); 226 246 227 247 struct adxl372_axis_lookup { 228 248 unsigned int bits; ··· 280 258 .modified = 1, \ 281 259 .channel2 = IIO_MOD_##axis, \ 282 260 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 283 - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 284 - BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ 261 + .info_mask_shared_by_type = \ 262 + BIT(IIO_CHAN_INFO_SCALE) | \ 263 + BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ 264 + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ 265 + .info_mask_shared_by_type_available = \ 266 + BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ 285 267 BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ 286 268 .scan_index = index, \ 287 269 .scan_type = { \ ··· 306 280 }; 307 281 308 282 struct adxl372_state { 283 + const struct adxl372_chip_info *chip_info; 309 284 int irq; 310 285 struct device *dev; 311 286 struct regmap *regmap; ··· 495 468 int ret; 496 469 497 470 /* 498 - * 3.3 ms per code is the scale factor of the TIME_ACT register for 499 - * ODR = 6400 Hz. It is 6.6 ms per code for ODR = 3200 Hz and below. 471 + * The scale factor of the TIME_ACT register depends on the ODR. 472 + * A higher scale factor is used at the maximum ODR and a lower 473 + * one at all other rates. 500 474 */ 501 - if (st->odr == ADXL372_ODR_6400HZ) 502 - scale_factor = 3300; 475 + if (st->odr == st->chip_info->max_odr) 476 + scale_factor = st->chip_info->act_time_scale_us; 503 477 else 504 - scale_factor = 6600; 478 + scale_factor = st->chip_info->act_time_scale_low_us; 505 479 506 480 reg_val = DIV_ROUND_CLOSEST(act_time_ms * 1000, scale_factor); 507 481 ··· 526 498 int ret; 527 499 528 500 /* 529 - * 13 ms per code is the scale factor of the TIME_INACT register for 530 - * ODR = 6400 Hz. It is 26 ms per code for ODR = 3200 Hz and below. 501 + * The scale factor of the TIME_INACT register depends on the ODR. 502 + * A higher scale factor is used at the maximum ODR and a lower 503 + * one at all other rates. 531 504 */ 532 - if (st->odr == ADXL372_ODR_6400HZ) 533 - scale_factor = 13; 505 + if (st->odr == st->chip_info->max_odr) 506 + scale_factor = st->chip_info->inact_time_scale_ms; 534 507 else 535 - scale_factor = 26; 508 + scale_factor = st->chip_info->inact_time_scale_low_ms; 536 509 537 510 res = DIV_ROUND_CLOSEST(inact_time_ms, scale_factor); 538 511 reg_val_h = (res >> 8) & 0xFF; ··· 743 714 if (ret < 0) 744 715 return ret; 745 716 746 - ret = adxl372_set_odr(st, ADXL372_ODR_6400HZ); 717 + ret = adxl372_set_odr(st, st->chip_info->max_odr); 747 718 if (ret < 0) 748 719 return ret; 749 720 ··· 803 774 *val2 = ADXL372_USCALE; 804 775 return IIO_VAL_INT_PLUS_MICRO; 805 776 case IIO_CHAN_INFO_SAMP_FREQ: 806 - *val = adxl372_samp_freq_tbl[st->odr]; 777 + *val = st->chip_info->samp_freq_tbl[st->odr]; 807 778 return IIO_VAL_INT; 808 779 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 809 - *val = adxl372_bw_freq_tbl[st->bw]; 780 + *val = st->chip_info->bw_freq_tbl[st->bw]; 810 781 return IIO_VAL_INT; 811 782 } 812 783 ··· 822 793 823 794 switch (info) { 824 795 case IIO_CHAN_INFO_SAMP_FREQ: 825 - odr_index = adxl372_find_closest_match(adxl372_samp_freq_tbl, 826 - ARRAY_SIZE(adxl372_samp_freq_tbl), 827 - val); 796 + odr_index = adxl372_find_closest_match(st->chip_info->samp_freq_tbl, 797 + st->chip_info->num_freqs, 798 + val); 828 799 ret = adxl372_set_odr(st, odr_index); 829 800 if (ret < 0) 830 801 return ret; 831 - /* 832 - * The timer period depends on the ODR selected. 833 - * At 3200 Hz and below, it is 6.6 ms; at 6400 Hz, it is 3.3 ms 834 - */ 802 + /* Recalculate activity time as the timer period depends on ODR */ 835 803 ret = adxl372_set_activity_time_ms(st, st->act_time_ms); 836 804 if (ret < 0) 837 805 return ret; 838 - /* 839 - * The timer period depends on the ODR selected. 840 - * At 3200 Hz and below, it is 26 ms; at 6400 Hz, it is 13 ms 841 - */ 806 + /* Recalculate inactivity time as the timer period depends on ODR */ 842 807 ret = adxl372_set_inactivity_time_ms(st, st->inact_time_ms); 843 808 if (ret < 0) 844 809 return ret; ··· 845 822 846 823 return ret; 847 824 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 848 - bw_index = adxl372_find_closest_match(adxl372_bw_freq_tbl, 849 - ARRAY_SIZE(adxl372_bw_freq_tbl), 850 - val); 825 + bw_index = adxl372_find_closest_match(st->chip_info->bw_freq_tbl, 826 + st->chip_info->num_freqs, 827 + val); 851 828 return adxl372_set_bandwidth(st, bw_index); 852 829 default: 853 830 return -EINVAL; ··· 975 952 } 976 953 977 954 return adxl372_set_interrupts(st, st->int1_bitmask, 0); 978 - } 979 - 980 - static ssize_t adxl372_show_filter_freq_avail(struct device *dev, 981 - struct device_attribute *attr, 982 - char *buf) 983 - { 984 - struct iio_dev *indio_dev = dev_to_iio_dev(dev); 985 - struct adxl372_state *st = iio_priv(indio_dev); 986 - int i; 987 - size_t len = 0; 988 - 989 - for (i = 0; i <= st->odr; i++) 990 - len += scnprintf(buf + len, PAGE_SIZE - len, 991 - "%d ", adxl372_bw_freq_tbl[i]); 992 - 993 - buf[len - 1] = '\n'; 994 - 995 - return len; 996 955 } 997 956 998 957 static ssize_t adxl372_get_fifo_enabled(struct device *dev, ··· 1144 1139 .set_trigger_state = adxl372_peak_dready_trig_set_state, 1145 1140 }; 1146 1141 1147 - static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400"); 1148 - static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available, 1149 - 0444, adxl372_show_filter_freq_avail, NULL, 0); 1142 + static int adxl372_read_avail(struct iio_dev *indio_dev, 1143 + struct iio_chan_spec const *chan, 1144 + const int **vals, int *type, int *length, 1145 + long mask) 1146 + { 1147 + struct adxl372_state *st = iio_priv(indio_dev); 1150 1148 1151 - static struct attribute *adxl372_attributes[] = { 1152 - &iio_const_attr_sampling_frequency_available.dev_attr.attr, 1153 - &iio_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr, 1154 - NULL, 1155 - }; 1156 - 1157 - static const struct attribute_group adxl372_attrs_group = { 1158 - .attrs = adxl372_attributes, 1159 - }; 1149 + switch (mask) { 1150 + case IIO_CHAN_INFO_SAMP_FREQ: 1151 + *vals = st->chip_info->samp_freq_tbl; 1152 + *type = IIO_VAL_INT; 1153 + *length = st->chip_info->num_freqs; 1154 + return IIO_AVAIL_LIST; 1155 + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 1156 + *vals = st->chip_info->bw_freq_tbl; 1157 + *type = IIO_VAL_INT; 1158 + /* 1159 + * Bandwidth cannot exceed half the sampling frequency 1160 + * (Nyquist), so limit available values based on current ODR. 1161 + */ 1162 + *length = st->odr + 1; 1163 + return IIO_AVAIL_LIST; 1164 + default: 1165 + return -EINVAL; 1166 + } 1167 + } 1160 1168 1161 1169 static const struct iio_info adxl372_info = { 1162 1170 .validate_trigger = &adxl372_validate_trigger, 1163 - .attrs = &adxl372_attrs_group, 1164 1171 .read_raw = adxl372_read_raw, 1165 1172 .write_raw = adxl372_write_raw, 1173 + .read_avail = adxl372_read_avail, 1166 1174 .read_event_config = adxl372_read_event_config, 1167 1175 .write_event_config = adxl372_write_event_config, 1168 1176 .read_event_value = adxl372_read_event_value, ··· 1191 1173 EXPORT_SYMBOL_NS_GPL(adxl372_readable_noinc_reg, "IIO_ADXL372"); 1192 1174 1193 1175 int adxl372_probe(struct device *dev, struct regmap *regmap, 1194 - int irq, const char *name) 1176 + int irq, const struct adxl372_chip_info *chip_info) 1195 1177 { 1196 1178 struct iio_dev *indio_dev; 1197 1179 struct adxl372_state *st; ··· 1207 1189 st->dev = dev; 1208 1190 st->regmap = regmap; 1209 1191 st->irq = irq; 1192 + st->chip_info = chip_info; 1210 1193 1211 1194 mutex_init(&st->threshold_m); 1212 1195 1213 1196 indio_dev->channels = adxl372_channels; 1214 1197 indio_dev->num_channels = ARRAY_SIZE(adxl372_channels); 1215 1198 indio_dev->available_scan_masks = adxl372_channel_masks; 1216 - indio_dev->name = name; 1199 + indio_dev->name = chip_info->name; 1217 1200 indio_dev->info = &adxl372_info; 1218 1201 indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; 1219 1202
+15 -1
drivers/iio/accel/adxl372.h
··· 10 10 11 11 #define ADXL372_REVID 0x03 12 12 13 + struct adxl372_chip_info { 14 + const char *name; 15 + const int *samp_freq_tbl; 16 + const int *bw_freq_tbl; 17 + unsigned int num_freqs; 18 + unsigned int act_time_scale_us; 19 + unsigned int act_time_scale_low_us; 20 + unsigned int inact_time_scale_ms; 21 + unsigned int inact_time_scale_low_ms; 22 + unsigned int max_odr; 23 + }; 24 + 25 + extern const struct adxl372_chip_info adxl372_chip_info; 26 + 13 27 int adxl372_probe(struct device *dev, struct regmap *regmap, 14 - int irq, const char *name); 28 + int irq, const struct adxl372_chip_info *chip_info); 15 29 bool adxl372_readable_noinc_reg(struct device *dev, unsigned int reg); 16 30 17 31 #endif /* _ADXL372_H_ */
+6 -4
drivers/iio/accel/adxl372_i2c.c
··· 20 20 21 21 static int adxl372_i2c_probe(struct i2c_client *client) 22 22 { 23 - const struct i2c_device_id *id = i2c_client_get_device_id(client); 23 + const struct adxl372_chip_info *chip_info; 24 24 struct regmap *regmap; 25 25 unsigned int regval; 26 26 int ret; 27 + 28 + chip_info = i2c_get_match_data(client); 27 29 28 30 regmap = devm_regmap_init_i2c(client, &adxl372_regmap_config); 29 31 if (IS_ERR(regmap)) ··· 40 38 dev_warn(&client->dev, 41 39 "I2C might not work properly with other devices on the bus"); 42 40 43 - return adxl372_probe(&client->dev, regmap, client->irq, id->name); 41 + return adxl372_probe(&client->dev, regmap, client->irq, chip_info); 44 42 } 45 43 46 44 static const struct i2c_device_id adxl372_i2c_id[] = { 47 - { "adxl372" }, 45 + { "adxl372", (kernel_ulong_t)&adxl372_chip_info }, 48 46 { } 49 47 }; 50 48 MODULE_DEVICE_TABLE(i2c, adxl372_i2c_id); 51 49 52 50 static const struct of_device_id adxl372_of_match[] = { 53 - { .compatible = "adi,adxl372" }, 51 + { .compatible = "adi,adxl372", .data = &adxl372_chip_info }, 54 52 { } 55 53 }; 56 54 MODULE_DEVICE_TABLE(of, adxl372_of_match);
+6 -4
drivers/iio/accel/adxl372_spi.c
··· 22 22 23 23 static int adxl372_spi_probe(struct spi_device *spi) 24 24 { 25 - const struct spi_device_id *id = spi_get_device_id(spi); 25 + const struct adxl372_chip_info *chip_info; 26 26 struct regmap *regmap; 27 + 28 + chip_info = spi_get_device_match_data(spi); 27 29 28 30 regmap = devm_regmap_init_spi(spi, &adxl372_spi_regmap_config); 29 31 if (IS_ERR(regmap)) 30 32 return PTR_ERR(regmap); 31 33 32 - return adxl372_probe(&spi->dev, regmap, spi->irq, id->name); 34 + return adxl372_probe(&spi->dev, regmap, spi->irq, chip_info); 33 35 } 34 36 35 37 static const struct spi_device_id adxl372_spi_id[] = { 36 - { "adxl372", 0 }, 38 + { "adxl372", (kernel_ulong_t)&adxl372_chip_info }, 37 39 { } 38 40 }; 39 41 MODULE_DEVICE_TABLE(spi, adxl372_spi_id); 40 42 41 43 static const struct of_device_id adxl372_of_match[] = { 42 - { .compatible = "adi,adxl372" }, 44 + { .compatible = "adi,adxl372", .data = &adxl372_chip_info }, 43 45 { } 44 46 }; 45 47 MODULE_DEVICE_TABLE(of, adxl372_of_match);