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: add g-range configuration

Introduce a mechanism to be able to configure and work with the available
g-ranges keeping the precision of 13 digits.

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

authored by

Lothar Rubusch and committed by
Jonathan Cameron
b99dbe3a 93ddd064

+79 -3
+79 -3
drivers/iio/accel/adxl345_core.c
··· 83 83 ADXL345_ODR_3200HZ, 84 84 }; 85 85 86 + enum adxl345_range { 87 + ADXL345_2G_RANGE = 0, 88 + ADXL345_4G_RANGE, 89 + ADXL345_8G_RANGE, 90 + ADXL345_16G_RANGE, 91 + }; 92 + 86 93 /* Certain features recommend 12.5 Hz - 400 Hz ODR */ 87 94 static const int adxl345_odr_tbl[][2] = { 88 95 [ADXL345_ODR_0P10HZ] = { 0, 97000 }, ··· 108 101 [ADXL345_ODR_800HZ] = { 800, 0 }, 109 102 [ADXL345_ODR_1600HZ] = { 1600, 0 }, 110 103 [ADXL345_ODR_3200HZ] = { 3200, 0 }, 104 + }; 105 + 106 + /* 107 + * Full resolution frequency table: 108 + * (g * 2 * 9.80665) / (2^(resolution) - 1) 109 + * 110 + * resolution := 13 (full) 111 + * g := 2|4|8|16 112 + * 113 + * 2g at 13bit: 0.004789 114 + * 4g at 13bit: 0.009578 115 + * 8g at 13bit: 0.019156 116 + * 16g at 16bit: 0.038312 117 + */ 118 + static const int adxl345_fullres_range_tbl[][2] = { 119 + [ADXL345_2G_RANGE] = { 0, 4789 }, 120 + [ADXL345_4G_RANGE] = { 0, 9578 }, 121 + [ADXL345_8G_RANGE] = { 0, 19156 }, 122 + [ADXL345_16G_RANGE] = { 0, 38312 }, 111 123 }; 112 124 113 125 struct adxl345_state { ··· 172 146 BIT(IIO_CHAN_INFO_CALIBBIAS), \ 173 147 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 174 148 BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 175 - .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 149 + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE) | \ 150 + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 176 151 .scan_index = (index), \ 177 152 .scan_type = { \ 178 153 .sign = 's', \ ··· 473 446 FIELD_PREP(ADXL345_BW_RATE_MSK, odr)); 474 447 } 475 448 449 + static int adxl345_find_range(struct adxl345_state *st, int val, int val2, 450 + enum adxl345_range *range) 451 + { 452 + int i; 453 + 454 + for (i = 0; i < ARRAY_SIZE(adxl345_fullres_range_tbl); i++) { 455 + if (val == adxl345_fullres_range_tbl[i][0] && 456 + val2 == adxl345_fullres_range_tbl[i][1]) { 457 + *range = i; 458 + return 0; 459 + } 460 + } 461 + 462 + return -EINVAL; 463 + } 464 + 465 + static int adxl345_set_range(struct adxl345_state *st, enum adxl345_range range) 466 + { 467 + return regmap_update_bits(st->regmap, ADXL345_REG_DATA_FORMAT, 468 + ADXL345_DATA_FORMAT_RANGE, 469 + FIELD_PREP(ADXL345_DATA_FORMAT_RANGE, range)); 470 + } 471 + 476 472 static int adxl345_read_avail(struct iio_dev *indio_dev, 477 473 struct iio_chan_spec const *chan, 478 474 const int **vals, int *type, 479 475 int *length, long mask) 480 476 { 481 477 switch (mask) { 478 + case IIO_CHAN_INFO_SCALE: 479 + *vals = (int *)adxl345_fullres_range_tbl; 480 + *type = IIO_VAL_INT_PLUS_MICRO; 481 + *length = ARRAY_SIZE(adxl345_fullres_range_tbl) * 2; 482 + return IIO_AVAIL_LIST; 482 483 case IIO_CHAN_INFO_SAMP_FREQ: 483 484 *vals = (int *)adxl345_odr_tbl; 484 485 *type = IIO_VAL_INT_PLUS_MICRO; ··· 525 470 __le16 accel; 526 471 unsigned int regval; 527 472 enum adxl345_odr odr; 473 + enum adxl345_range range; 528 474 int ret; 529 475 530 476 switch (mask) { ··· 544 488 *val = sign_extend32(le16_to_cpu(accel), 12); 545 489 return IIO_VAL_INT; 546 490 case IIO_CHAN_INFO_SCALE: 547 - *val = 0; 548 - *val2 = st->info->uscale; 491 + ret = regmap_read(st->regmap, ADXL345_REG_DATA_FORMAT, &regval); 492 + if (ret) 493 + return ret; 494 + range = FIELD_GET(ADXL345_DATA_FORMAT_RANGE, regval); 495 + *val = adxl345_fullres_range_tbl[range][0]; 496 + *val2 = adxl345_fullres_range_tbl[range][1]; 549 497 return IIO_VAL_INT_PLUS_MICRO; 550 498 case IIO_CHAN_INFO_CALIBBIAS: 551 499 ret = regmap_read(st->regmap, ··· 581 521 int val, int val2, long mask) 582 522 { 583 523 struct adxl345_state *st = iio_priv(indio_dev); 524 + enum adxl345_range range; 584 525 enum adxl345_odr odr; 585 526 int ret; 586 527 ··· 607 546 return ret; 608 547 609 548 ret = adxl345_set_odr(st, odr); 549 + if (ret) 550 + return ret; 551 + break; 552 + case IIO_CHAN_INFO_SCALE: 553 + ret = adxl345_find_range(st, val, val2, &range); 554 + if (ret) 555 + return ret; 556 + 557 + ret = adxl345_set_range(st, range); 610 558 if (ret) 611 559 return ret; 612 560 break; ··· 811 741 switch (mask) { 812 742 case IIO_CHAN_INFO_CALIBBIAS: 813 743 return IIO_VAL_INT; 744 + case IIO_CHAN_INFO_SCALE: 745 + return IIO_VAL_INT_PLUS_MICRO; 814 746 case IIO_CHAN_INFO_SAMP_FREQ: 815 747 return IIO_VAL_INT_PLUS_MICRO; 816 748 default: ··· 1152 1080 * undesired behavior. 1153 1081 */ 1154 1082 ret = adxl345_set_odr(st, ADXL345_ODR_200HZ); 1083 + if (ret) 1084 + return ret; 1085 + 1086 + ret = adxl345_set_range(st, ADXL345_16G_RANGE); 1155 1087 if (ret) 1156 1088 return ret; 1157 1089