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: adxl345: extend sample frequency adjustments

Introduce enums and functions to work with the sample frequency
adjustments. Let the sample frequency adjust via IIO and configure
a reasonable default.

Replace the old static sample frequency handling. During adjustment of
bw registers, measuring is disabled and afterwards enabled again.

Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
Link: https://patch.msgid.link/20250510224405.17910-2-l.rubusch@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Lothar Rubusch and committed by
Jonathan Cameron
93ddd064 9182f3b4

+118 -34
+1 -1
drivers/iio/accel/adxl345.h
··· 69 69 * BW_RATE bits - Bandwidth and output data rate. The default value is 70 70 * 0x0A, which translates to a 100 Hz output data rate 71 71 */ 72 - #define ADXL345_BW_RATE GENMASK(3, 0) 72 + #define ADXL345_BW_RATE_MSK GENMASK(3, 0) 73 73 #define ADXL345_BW_LOW_POWER BIT(4) 74 74 #define ADXL345_BASE_RATE_NANO_HZ 97656250LL 75 75
+117 -33
drivers/iio/accel/adxl345_core.c
··· 64 64 [ADXL345_TAP_TIME_DUR] = ADXL345_REG_DUR, 65 65 }; 66 66 67 + enum adxl345_odr { 68 + ADXL345_ODR_0P10HZ = 0, 69 + ADXL345_ODR_0P20HZ, 70 + ADXL345_ODR_0P39HZ, 71 + ADXL345_ODR_0P78HZ, 72 + ADXL345_ODR_1P56HZ, 73 + ADXL345_ODR_3P13HZ, 74 + ADXL345_ODR_6P25HZ, 75 + ADXL345_ODR_12P50HZ, 76 + ADXL345_ODR_25HZ, 77 + ADXL345_ODR_50HZ, 78 + ADXL345_ODR_100HZ, 79 + ADXL345_ODR_200HZ, 80 + ADXL345_ODR_400HZ, 81 + ADXL345_ODR_800HZ, 82 + ADXL345_ODR_1600HZ, 83 + ADXL345_ODR_3200HZ, 84 + }; 85 + 86 + /* Certain features recommend 12.5 Hz - 400 Hz ODR */ 87 + static const int adxl345_odr_tbl[][2] = { 88 + [ADXL345_ODR_0P10HZ] = { 0, 97000 }, 89 + [ADXL345_ODR_0P20HZ] = { 0, 195000 }, 90 + [ADXL345_ODR_0P39HZ] = { 0, 390000 }, 91 + [ADXL345_ODR_0P78HZ] = { 0, 781000 }, 92 + [ADXL345_ODR_1P56HZ] = { 1, 562000 }, 93 + [ADXL345_ODR_3P13HZ] = { 3, 125000 }, 94 + [ADXL345_ODR_6P25HZ] = { 6, 250000 }, 95 + [ADXL345_ODR_12P50HZ] = { 12, 500000 }, 96 + [ADXL345_ODR_25HZ] = { 25, 0 }, 97 + [ADXL345_ODR_50HZ] = { 50, 0 }, 98 + [ADXL345_ODR_100HZ] = { 100, 0 }, 99 + [ADXL345_ODR_200HZ] = { 200, 0 }, 100 + [ADXL345_ODR_400HZ] = { 400, 0 }, 101 + [ADXL345_ODR_800HZ] = { 800, 0 }, 102 + [ADXL345_ODR_1600HZ] = { 1600, 0 }, 103 + [ADXL345_ODR_3200HZ] = { 3200, 0 }, 104 + }; 105 + 67 106 struct adxl345_state { 68 107 const struct adxl345_chip_info *info; 69 108 struct regmap *regmap; ··· 146 107 BIT(IIO_CHAN_INFO_CALIBBIAS), \ 147 108 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 148 109 BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 110 + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 149 111 .scan_index = (index), \ 150 112 .scan_type = { \ 151 113 .sign = 's', \ ··· 423 383 return _adxl345_set_tap_time(st, ADXL345_TAP_TIME_LATENT, val_fract_us); 424 384 } 425 385 386 + static int adxl345_find_odr(struct adxl345_state *st, int val, 387 + int val2, enum adxl345_odr *odr) 388 + { 389 + int i; 390 + 391 + for (i = 0; i < ARRAY_SIZE(adxl345_odr_tbl); i++) { 392 + if (val == adxl345_odr_tbl[i][0] && 393 + val2 == adxl345_odr_tbl[i][1]) { 394 + *odr = i; 395 + return 0; 396 + } 397 + } 398 + 399 + return -EINVAL; 400 + } 401 + 402 + static int adxl345_set_odr(struct adxl345_state *st, enum adxl345_odr odr) 403 + { 404 + return regmap_update_bits(st->regmap, ADXL345_REG_BW_RATE, 405 + ADXL345_BW_RATE_MSK, 406 + FIELD_PREP(ADXL345_BW_RATE_MSK, odr)); 407 + } 408 + 409 + static int adxl345_read_avail(struct iio_dev *indio_dev, 410 + struct iio_chan_spec const *chan, 411 + const int **vals, int *type, 412 + int *length, long mask) 413 + { 414 + switch (mask) { 415 + case IIO_CHAN_INFO_SAMP_FREQ: 416 + *vals = (int *)adxl345_odr_tbl; 417 + *type = IIO_VAL_INT_PLUS_MICRO; 418 + *length = ARRAY_SIZE(adxl345_odr_tbl) * 2; 419 + return IIO_AVAIL_LIST; 420 + } 421 + 422 + return -EINVAL; 423 + } 424 + 426 425 static int adxl345_read_raw(struct iio_dev *indio_dev, 427 426 struct iio_chan_spec const *chan, 428 427 int *val, int *val2, long mask) 429 428 { 430 429 struct adxl345_state *st = iio_priv(indio_dev); 431 430 __le16 accel; 432 - long long samp_freq_nhz; 433 431 unsigned int regval; 432 + enum adxl345_odr odr; 434 433 int ret; 435 434 436 435 switch (mask) { ··· 507 428 ret = regmap_read(st->regmap, ADXL345_REG_BW_RATE, &regval); 508 429 if (ret) 509 430 return ret; 510 - 511 - samp_freq_nhz = ADXL345_BASE_RATE_NANO_HZ << 512 - (regval & ADXL345_BW_RATE); 513 - *val = div_s64_rem(samp_freq_nhz, NANOHZ_PER_HZ, val2); 514 - 515 - return IIO_VAL_INT_PLUS_NANO; 431 + odr = FIELD_GET(ADXL345_BW_RATE_MSK, regval); 432 + *val = adxl345_odr_tbl[odr][0]; 433 + *val2 = adxl345_odr_tbl[odr][1]; 434 + return IIO_VAL_INT_PLUS_MICRO; 516 435 } 517 436 518 437 return -EINVAL; ··· 521 444 int val, int val2, long mask) 522 445 { 523 446 struct adxl345_state *st = iio_priv(indio_dev); 524 - s64 n; 447 + enum adxl345_odr odr; 448 + int ret; 449 + 450 + ret = adxl345_set_measure_en(st, false); 451 + if (ret) 452 + return ret; 525 453 526 454 switch (mask) { 527 455 case IIO_CHAN_INFO_CALIBBIAS: ··· 534 452 * 8-bit resolution at +/- 2g, that is 4x accel data scale 535 453 * factor 536 454 */ 537 - return regmap_write(st->regmap, 538 - ADXL345_REG_OFS_AXIS(chan->address), 539 - val / 4); 455 + ret = regmap_write(st->regmap, 456 + ADXL345_REG_OFS_AXIS(chan->address), 457 + val / 4); 458 + if (ret) 459 + return ret; 460 + break; 540 461 case IIO_CHAN_INFO_SAMP_FREQ: 541 - n = div_s64(val * NANOHZ_PER_HZ + val2, 542 - ADXL345_BASE_RATE_NANO_HZ); 462 + ret = adxl345_find_odr(st, val, val2, &odr); 463 + if (ret) 464 + return ret; 543 465 544 - return regmap_update_bits(st->regmap, ADXL345_REG_BW_RATE, 545 - ADXL345_BW_RATE, 546 - clamp_val(ilog2(n), 0, 547 - ADXL345_BW_RATE)); 466 + ret = adxl345_set_odr(st, odr); 467 + if (ret) 468 + return ret; 469 + break; 470 + default: 471 + return -EINVAL; 548 472 } 549 473 550 - return -EINVAL; 474 + return adxl345_set_measure_en(st, true); 551 475 } 552 476 553 477 static int adxl345_read_event_config(struct iio_dev *indio_dev, ··· 742 654 case IIO_CHAN_INFO_CALIBBIAS: 743 655 return IIO_VAL_INT; 744 656 case IIO_CHAN_INFO_SAMP_FREQ: 745 - return IIO_VAL_INT_PLUS_NANO; 657 + return IIO_VAL_INT_PLUS_MICRO; 746 658 default: 747 659 return -EINVAL; 748 660 } ··· 754 666 755 667 adxl345_set_measure_en(st, false); 756 668 } 757 - 758 - static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( 759 - "0.09765625 0.1953125 0.390625 0.78125 1.5625 3.125 6.25 12.5 25 50 100 200 400 800 1600 3200" 760 - ); 761 - 762 - static struct attribute *adxl345_attrs[] = { 763 - &iio_const_attr_sampling_frequency_available.dev_attr.attr, 764 - NULL 765 - }; 766 - 767 - static const struct attribute_group adxl345_attrs_group = { 768 - .attrs = adxl345_attrs, 769 - }; 770 669 771 670 static int adxl345_set_fifo(struct adxl345_state *st) 772 671 { ··· 1006 931 } 1007 932 1008 933 static const struct iio_info adxl345_info = { 1009 - .attrs = &adxl345_attrs_group, 1010 934 .read_raw = adxl345_read_raw, 1011 935 .write_raw = adxl345_write_raw, 936 + .read_avail = adxl345_read_avail, 1012 937 .write_raw_get_fmt = adxl345_write_raw_get_fmt, 1013 938 .read_event_config = adxl345_read_event_config, 1014 939 .write_event_config = adxl345_write_event_config, ··· 1073 998 indio_dev->channels = adxl345_channels; 1074 999 indio_dev->num_channels = ARRAY_SIZE(adxl345_channels); 1075 1000 indio_dev->available_scan_masks = adxl345_scan_masks; 1001 + 1002 + /* 1003 + * Using I2C at 100kHz would limit the maximum ODR to 200Hz, operation 1004 + * at an output rate above the recommended maximum may result in 1005 + * undesired behavior. 1006 + */ 1007 + ret = adxl345_set_odr(st, ADXL345_ODR_200HZ); 1008 + if (ret) 1009 + return ret; 1076 1010 1077 1011 /* Reset interrupts at start up */ 1078 1012 ret = regmap_write(st->regmap, ADXL345_REG_INT_ENABLE, 0x00);